String 在流中找到单词?
给定一个无限的字符流和一个字符串列表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”时,你有两个选择: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”,并且您的
#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>>文本;
搜索(文本);
删除(根);
}
不错,但我正在寻找递归解决方案。我只是想知道这是否是错误的,或者它是否有一个我没有处理的极端情况。我将这个答案标记为正确的,只是因为它告诉你正确的算法,但原始问题是不同的。