您的位置:首页 > 其它

hdu3065

2016-07-29 16:00 239 查看
模式串可能相互包含或重叠

#include<iostream>
#include<cstring>
#include<queue>
#include<map>
#include<algorithm>
#include<cstdio>
using namespace std;

const int maxn =26;
char ss[1010][55];
int vis[1010],cnt[1010];

struct Node
{
Node *next[maxn];
Node *pre;//前缀指针
int last,id;
Node ()//初始化数据
{
memset(next, 0, sizeof (next));
pre =NULL, last = 0,id=0;
}
};

Node *root;
void Init ()
{
root = new Node;
}

void Insert (char *s,int id)
{
if (!s[0]) return ;

Node *p = root;
for (int i = 0; s[i]; i++)
{
int k=s[i]-'A';//要记得随时更改
if (!p -> next[k])
p -> next[k] = new Node;
p = p -> next[k];
}
p -> last++;//记录该节点单词总共插入的次数
p->id=id;//记录该节点单词的序号
}

void Build ()//建立前缀指针
{
queue <Node*> qu;
for (int i = 0; i < maxn; i++)
if (root -> next[i])
{
root -> next[i] -> pre = root;
qu.push (root -> next[i]);//层次遍历建立前缀指针
}

while (!qu.empty ())
{
Node *temp = qu.front (); qu.pop ();
for (int i = 0; i < maxn; i++)
{
Node *pp = temp -> next[i];
if (pp)
{
Node *par = temp -> pre;
do
{
if (par -> next[i])
{
pp -> pre = par -> next[i];
break;
}
else
par = par -> pre;
} while (par);

if (!par)
pp -> pre = root;

qu.push (pp);
}
}
}
}

void Query(char *s)
{
if (!s[0]) return;
Node *p = root;
for (int i = 0; s[i]; i++)
{
int k=s[i]-'A';
while (p != root && !p -> next[k])
p = p -> pre;

p = p -> next[k];//移动到匹配位置
if (!p)
p = root;//若匹配失败,移到根节点重新匹配
// cout<<p->id<<" & "<<endl;
Node *pp = p;
// pp->id-=100;
// cout<<p->id<<" & "<<endl;
while (pp != root && pp -> last != -1)//若匹配成功,last>0,代表该节点的单词数量,
{ //否则表示该节点没有单词
if(pp->last>0)
{
cnt[pp->id]++;//统计该单词出现的次数
vis[pp->id]=1;
}
// pp -> last = -1;//模式串可能相互包含或重叠
pp = pp -> pre;
}
}

}

void DelTree (Node *s)
{
if (!s) return ;

for (int i = 0; i < maxn; i++)
{
if (s -> next[i])
DelTree (s -> next[i]);
}
delete s;
}

char st[2000010],source[2000010];
int main()
{
int n;
while(~scanf ("%d",&n))
{
Init ();
for (int i = 1; i <= n; i++)
{
scanf ("%s", ss[i]);
Insert (ss[i],i);
}
getchar();
Build ();
memset(vis,0,sizeof(vis));
memset(cnt,0,sizeof(cnt));
scanf ("%s",st);
int h=0;
int len=strlen(st);
for(int i=0;i<=len;i++)//必须到strlen,这样才能给字符串source末尾加'\0'
{
if(st[i]>='A'&&st[i]<='Z')
source[h++]=st[i];
else
{
source[h]='\0';
Query(source);
h=0;
}
}
for(int j=1;j<=n;j++)
{
if(vis[j])
{
printf("%s: ",ss[j]);
printf("%d\n",cnt[j]);
}
}

DelTree (root);
}

return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  AC自动机