洛谷P3796
都说了是AC自动机模板。。。
get_fail每次都很恼火
因为优化很多,但隔这么久,第二次看还是更懂一点了
下一次应该就把板子定了吧。。。
#include
#define x s[i]-'a'
using namespace std;
const int N=1e6+10;
int T;
int n;
int ans[155];
int t[60005][30],tot;
int g[60005];
int bl[60005];
int f[60005];
void init()
{
memset(t,0,sizeof(t));
memset(g,0,sizeof(g));
memset(bl,0,sizeof(bl));
memset(f,0,sizeof(f));tot=0;
memset(ans,0,sizeof(ans));
}
void add(char s[],int i)
{
int p=0;
for(int i=0;s[i];i++)
{
if(!t[p][x])t[p][x]=++tot;
p=t[p][x];
}g[p]++;bl[p]=i;
}
void get_fail()
{
queue<int>q;
int p=0;
for(int i=0;i<26;i++)
if(t[p][i])q.push(t[p][i]);
while(!q.empty())
{
int u=q.front();q.pop();
for(int i=0;i<26;i++)
{
int v=t[u][i],as=f[u];
if(v)
{
while(as&&!t[as][i])as=f[as];
//没有这个点,就失败,跳fail指针
f[v]=t[as][i];
q.push(v);
}
else t[u][i]=t[as][i];
//很迷的东西对吧,实际上是优化
//下面没有节点了,就把fail指针的节点变为当前子节点,反正都是要走到这的
//虽然原trie树改了,但改了计算时没有影响正确性
}
}
}
void find(char s[])
{
int p=0;
for(int i=0;s[i];i++)
{
p=t[p][x];
for(int j=p;j;j=f[j])ans[bl[j]]++;
//统计
}
}
char s[155][102];
char tt[N];
int main()
{
while(scanf("%d",&n)&&n)
{
init();
for(int i=1;i<=n;i++)
{
scanf("%s",s[i]);
add(s[i],i);
}
get_fail();
scanf("%s",tt);
find(tt);
int maxx=0;
for(int i=1;i<=n;i++)maxx=max(maxx,ans[i]);printf("%d\n",maxx);
for(int i=1;i<=n;i++)if(maxx==ans[i])printf("%s\n",s[i]);
}
}
加强版
新晋毒瘤模板!
#include
using namespace std;
const int N=2e6+10;
int t[N][30],all;
int f[N],las[N];
int val[N],sam[N];
void putin(char *s,int bt)
{
int p=0;
for(int i=0;s[i];i++)
{
int now=s[i]-'a';
if(!t[p][now])t[p][now]=++all;
p=t[p][now];
}
if(!val[p])val[p]=bt;
else sam[bt]=val[p];
}
void get_fail()
{
queue<int>q;
int p=0;
for(int i=0;i<26;i++)
if(t[p][i])q.push(t[p][i]);
while(!q.empty())
{
int u=q.front();q.pop();
for(int i=0;i<26;i++)
{
p=t[u][i];
if(!p)
{
t[u][i]=t[f[u]][i];
continue;
}
q.push(p);
int pre=f[u];
while(pre&&!t[pre][i])pre=f[pre];
f[p]=t[pre][i];
las[p]=val[f[p]]?f[p]:las[f[p]];
}
}
}
int ans[N];
void work(char *s)
{
int p=0;
for(int i=0;s[i];i++)
{
int now=s[i]-'a';
p=t[p][now];
int pre=0;
pre=val[p]?p:las[p];
while(pre)
{
ans[val[pre]]++;
pre=las[pre];
}
}
}
int n;
char s[N];
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%s",s);
putin(s,i);
}
get_fail();
scanf("%s",s);
work(s);
for(int i=1;i<=n;i++)
{
if(sam[i])printf("%d\n",ans[sam[i]]);
else printf("%d\n",ans[i]);
}
}