给n个串,每次询问x号串和y号串的最长公共子串的长度,这个子串必须是n个串中某个串的前缀
做法是把n个串建成AC自动机,前缀树中每个节点都当做结尾节点,val赋为trie树深度
然后把x串丢进自动机里,把匹配到的前缀节点染个色,再把y串丢进去,遇到同样颜色的前缀节点就更新一下答案
#include<bits/stdc++.h> #include<stdio.h> #include<algorithm> #include<queue> #include<string.h> #include<iostream> #include<math.h> #include<set> #include<map> #include<vector> #include<iomanip> using namespace std; #define ll long long #define pb push_back #define FOR(a) for(int i=1;i<=a;i++) const int inf=0x3f3f3f3f; const int maxn=1e5+91; const int mod=1e9+7; const int sigma=26; struct automata{ int ch[maxn][sigma]; int val[maxn]; int f[maxn]; int color[maxn]; int sz; int newnode(){ memset(ch[sz],0,sizeof(ch[sz])); f[sz]=val[sz]=color[sz]=0; return sz++; } void init(){ memset(val,0,sizeof(val)); sz=0; newnode(); } void insert(char *s,int v){ int u=0; int len=strlen(s); for(int i=0;i<len;i++){ int id=s[i]-'a'; if(!ch[u][id])ch[u][id]=newnode(); val[ch[u][id]]=val[u]+1; u=ch[u][id]; } } void build(){ queue<int>q; q.push(0); while(!q.empty()){ int u=q.front();q.pop(); for(int i=0;i<sigma;i++){ int v=ch[u][i]; if(!v)ch[u][i]=ch[f[u]][i]; else q.push(v); if(u&&v)f[v]=ch[f[u]][i]; } } } void update(char *s,int x){ int len=strlen(s); int u=0; for(int i=0;i<len;i++){ int id=s[i]-'a'; u=ch[u][id]; int tmp=u; while(tmp){ color[tmp]=x; tmp=f[tmp]; } } } int query(char *s,int x){ int len=strlen(s); int u=0; int ans=0; for(int i=0;i<len;i++){ int id=s[i]-'a'; u=ch[u][id]; int tmp=u; while(tmp){ if(color[tmp]==x){ ans=max(ans,val[tmp]); } tmp=f[tmp]; } } return ans; } }ac; char s[maxn]; int pos[maxn]; int main(){ int T;scanf("%d",&T); while(T--){ int n;scanf("%d",&n); ac.init(); int d=1; for(int i=1;i<=n;i++){ pos[i]=d; scanf("%s",s+d); ac.insert(s+d,0); int len=strlen(s+d); d+=len+1; } ac.build(); int q; scanf("%d",&q); int id=1; while(q--){ int x,y; scanf("%d%d",&x,&y); ac.update(s+pos[x],id); int ans=ac.query(s+pos[y],id); ++id; printf("%d ",ans); } } }接下来一段时间搞搞字符串吧~