String 在流中找到单词?

String 在流中找到单词?,string,algorithm,recursion,String,Algorithm,Recursion,给定一个无限的字符流和一个字符串列表L,创建一个函数,当在流处理过程中识别出L中的一个单词时,该函数将调用外部API 例如: L=[“确定”、“测试”、“一次”、“尝试”、“尝试”] 流=a、b、c、o、k、d、e、f、t、r、y、i、n、g 对外部API的调用将在遇到“k”时发生,在遇到“y”时再次发生,在“g”时再次发生 我的想法是: 从列表中创建trie,并在线性时间内从流中读取数据时导航节点。但是如果你只做简单的trie,就会有一个bug 假设您有单词“abxyz”和“xyw”,并且您的

给定一个无限的字符流和一个字符串列表L,创建一个函数,当在流处理过程中识别出L中的一个单词时,该函数将调用外部API

例如: L=[“确定”、“测试”、“一次”、“尝试”、“尝试”]

流=a、b、c、o、k、d、e、f、t、r、y、i、n、g

对外部API的调用将在遇到“k”时发生,在遇到“y”时再次发生,在“g”时再次发生

我的想法是: 从列表中创建trie,并在线性时间内从流中读取数据时导航节点。但是如果你只做简单的trie,就会有一个bug

假设您有单词“abxyz”和“xyw”,并且您的输入是“abxyw”。在这种情况下,您无法用trie识别“xyw”

因此,搜索应修改如下:

让我们看一下上面的用例“abxyw”。我们开始搜索,发现所有元素都在“x”之前。当你得到“x”时,你有两个选择:

  • 检查当前元素是否等于trie的head,如果它等于trie的head,则调用递归搜索

  • 继续到当前单词的结尾。在这种情况下,对于给定的输入,它将返回false,但是对于我们在第1点开始的递归搜索,它将返回true

  • 下面是我修改过的搜索,但我认为它有缺陷,可以改进。有什么建议吗

    #define SIZE 26
    struct tri{
        int complete;
        struct tri *child[SIZE];
    };
    
    void insert(char *c, struct tri **t)
    {
        struct tri *current = *t;
        while(*c != '\0')
        {
            int i;
            int letter = *c - 'a';
            if(current->child[letter] == NULL) {
                current->child[letter] = malloc(sizeof(*current));
                memset(current->child[letter], 0, sizeof(struct tri));
            }
            current = current->child[letter];
            c++;
        }
        current->complete = 1;
    }
    
    struct tri *t;
    int flag = 0;
    int found(char *c, struct tri *tt)
    {
        struct tri *current = tt;
    
        if (current == NULL)
            return 0;
        while(*c != '\0')
        {
            int i;
            int letter = *c - 'a';
            /* if this is the first char then recurse from begining*/
            if (t->child[letter] != NULL)
                flag = found(c+1, t->child[letter]);
            if (flag == 1)
                return 1;
            if(!flag && current->child[letter] == NULL) {
                return 0;
            }
            current = current->child[letter];
            c++;
        }
        return current->complete;
    }
    
    int main()
    {
        int i;
        t = malloc(sizeof(*t));
        t->complete = 0;
        memset(t, 0, sizeof(struct tri));
    
        insert("weathez", &t);
        insert("eather", &t);
        insert("weather", &t);
        (1 ==found("weather", t))?printf("found\n"):printf("not found\n");
        return 0;
    }
    

    你想做的正是你想做的

    您可以查看我的Aho Corasick实现。它是以竞赛为导向的,所以可能不注重可读性,但我认为这很清楚:

    typedef向量VI;
    结构节点{
    整数大小;
    节点*失败,*输出;
    VI id;
    下一张地图;
    };
    typedef对P;
    typedef-map-MCP;
    节点*根;
    内联void init(){
    根=新节点;
    根->大小=0;
    root->output=root->fail=NULL;
    }
    节点*添加(字符串&s,整数u,整数c=0,节点*p=root){
    if(p==NULL){
    p=新节点;
    p->size=c;
    p->fail=p->output=NULL;
    }
    如果(c==s.size())p->id.push_back(u);
    否则{
    如果(非p->next.count(s[c])p->next[s[c]]=NULL;
    p->next[s[c]]=添加(s,u,c+1,p->next[s[c]];
    }
    返回p;
    }
    无效填充\失败\输出(){
    队列Q;
    for(MCP::iterator it=root->next.begin();
    它!=根->下一个.end();++它)
    Q.push(配对(it->first,P(root,it->second));
    while(不是Q.empty()){
    节点*pare=Q.front().second.first;
    节点*fill=Q.front().second.second;
    charc=Q.front().first;Q.pop();
    而(pare!=root&&!pare->fail->next.count(c))
    pare=pare->fail;
    如果(pare==root)填充->失败=root;
    else fill->fail=pare->fail->next[c];
    如果(填充->失败->id.size()!=0)
    填充->输出=填充->失败;
    否则填充->输出=填充->失败->输出;
    对于(MCP::iterator it=fill->next.begin();
    它!=填充->下一个.end();++它)
    推送(配对(it->first,P(fill,it->second));
    }
    }
    无效匹配(内部c、VI和id){
    对于(int i=0;iid);
    q=q->输出;
    }
    }
    if(p!=根){
    p=p->fail;
    i=j-p->尺寸;
    }
    否则i=++j;
    }
    }
    无效擦除(节点*p=根){
    对于(MCP::iterator it=p->next.begin();
    it!=p->next.end();+it)
    擦除(它->秒);
    删除p;
    }
    int main(){
    init();
    int n;
    cin>>n;
    对于(int i=0;i>s;
    加(s,i);
    }
    填充失败输出();
    字符串文本;
    cin>>文本;
    搜索(文本);
    删除(根);
    }
    
    不错,但我正在寻找递归解决方案。我只是想知道这是否是错误的,或者它是否有一个我没有处理的极端情况。我将这个答案标记为正确的,只是因为它告诉你正确的算法,但原始问题是不同的。