傻逼出题人没说单词可以重复
但是还是好写
你就不用把end那里每次修改
查的时候n^2找到第一个和他相同的就行了
而且使用AC自动机做这个题有一个小trick:
我们的模板串需要拼合
但是良心的样例告诉我们不能直接拼合,所以我们增大一个字符集,然后拼合的时候加入一个“{”(这是‘a’+26)。
然后AC——AUTOMATION 完
#include<bits/stdc++.h>
using namespace std;
const int N=2e6+301;
struct Result{
int sum,pos;
}Ans[N];
struct A_C_AUTO{
struct Node{
int end;
int fail;
int cnt;
int vis[31];
}AC[N];
int cnt;
inline void Clear(int p){
memset(AC[p].vis,0,sizeof(AC[p].vis));
AC[p].end=0;
AC[p].fail=0;
AC[p].cnt=0;
}
inline void Build(string S,int Id){
int now=0;
int R=S.length();
for(int i=0;i<R;i++){
if(!AC[now].vis[S[i]-'a']){
cnt++;
Clear(cnt);
AC[now].vis[S[i]-'a']=cnt;
}
now=AC[now].vis[S[i]-'a'];
}
if(!AC[now].end)
AC[now].end=Id;
// AC[now].cnt;
}
inline void Get_Fail(){
queue<int> Q;
for(int i=0;i<27;i++){
if(AC[0].vis[i]){
AC[AC[0].vis[i]].fail=0;
Q.push(AC[0].vis[i]);
}
}
while(!Q.empty()){
int x=Q.front();
Q.pop();
for(int i=0;i<27;i++){
if(AC[x].vis[i]){
AC[AC[x].vis[i]].fail=AC[AC[x].fail].vis[i];
Q.push(AC[x].vis[i]);
}
else AC[x].vis[i]=AC[AC[x].fail].vis[i];
}
}
}
inline void Query(string S){
int now=0;
int R=S.length();
for(int i=0;i<R;i++){
now=AC[now].vis[S[i]-'a'];
for(int t=now;t;t=AC[t].fail){
Ans[AC[t].end].sum+=1;
}
}
}
}ACM;
int n;
string s[N]={};
string Key;
int main(){
// freopen("P3966.in","r",stdin);
// cout<<(char)('a'+26);
cin>>n;
// cout<<n;
Key="";
ACM.Clear(0);
for(int i=1;i<=n;i++){
cin>>s[i];
Ans[i].pos=i;
Ans[i].sum=0;
ACM.Build(s[i],i);
Key=Key+(char)('a'+26)+s[i];
}
// cout<<Key<<'\n';
ACM.AC[0].fail=0;
ACM.Get_Fail();
ACM.Query(Key);
for(int i=1;i<=n;i++){
if(Ans[i].sum!=0)
cout<<Ans[i].sum<<'\n';
else for(int j=1;j<i;j++){
if(s[i]==s[j]){
cout<<Ans[j].sum<<'\n';
break;
}
}
}
return 0;
}