HDU6138 Fleet of the Eternal Throne
Mean
给定\(n\)个字符串,\(m\)次询问\((m<=100)\),每次询问第\(L\)个字符串和第\(R\)个字符串的所有公共子串中,最长的公共子串,满足其是\(n\)个字符串中任意一个的前缀,输出其最长的长度。
Sol
GSAM
注意到\(m\)只有100,每次暴力的将询问的\(L\)串和\(R\)串建出广义后缀自动机,每个状态记录其在\(L\)串中出现的次数和在\(R\)串中出现的次数\(siz[i][0]和siz[i][1]\),跑一遍\(fail树\),向上传递维护一下。
随后依次遍历\(n\)个字符串,注意不允许失配,因为要求的是前缀。
把所有的合法前缀长度求个\(max\)即可。
复杂度\(O(nm)\).
Code
#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=(a);i<=(b);++i)
#define dep(i,a,b) for(int i=(a);i>=(b);--i)
#define lowbit(x) (x&(-x))
#define debug(x) cout<<#x<<" :"<<x<<endl
#define debug1(x) cout<<#x<<" :"<<x<<" "
using namespace std;
typedef unsigned long long ull;
typedef long long ll;
const int N=2e5+20;
const int MAX=10000007;
inline int read() {
char c=getchar();int x=0,f=1;
while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
while(c>='0'&&c<='9'){x=x*10+c-'0',c=getchar();}
return x*f;
}
inline void out(int x) {
if(x>9) out(x/10);
putchar(x%10+'0');
}
int q[N];
struct Node{
int len,fa;
int ch[10];
}node[N*2];
int tot=1,last=1;
int siz[N*2][3];
int extend(int c,int last,int id){
if(node[last].ch[c]){
int p = last,x = node[p].ch[c];
if(node[p].len + 1 == node[x].len){//特判1
siz[x][id]=1;
return x;
}
else{//特判2
int y = ++tot;node[y].len = node[p].len+1;
for(int i=0;i<=9;++i)node[y].ch[i] = node[x].ch[i];
while(p&&node[p].ch[c]==x)node[p].ch[c]=y,p=node[p].fa;
node[y].fa=node[x].fa,node[x].fa=y;
siz[y][id]=1;
return y;
}
}
int p = last ,np = last = ++tot;
node[np].len = node[p].len + 1;
for(;p && !node[p].ch[c]; p = node[p].fa){
node[p].ch[c] = np;
}
if(!p)node[np].fa = 1;
else{
int q = node[p].ch[c];
if(node[q].len == node[p].len + 1){
node[np].fa = q;
}
else{
int nq = ++tot;
node[nq] = node[q];
node[nq].len = node[p].len+1;
node[q].fa = node[np].fa = nq;
for(;p && node[p].ch[c] == q;p = node[p].fa){
node[p].ch[c] = nq;
}
}
}
siz[last][id]=1;
return last;
}
void init(){
rep(i,0,tot){
rep(j,0,25){
node[i].ch[j]=0;
}
node[i].fa=0;
siz[i][0]=siz[i][1]=0;
}
tot=last=1;
}
int T,n,m;
string s[N];
char p[N];
int in[N*2];
void solve(){
memset(in,0,sizeof in);
queue<int>Q;
rep(i,2,tot){
in[node[i].fa]++;
}
rep(i,1,tot){
if(!in[i])Q.push(i);
}
while(!Q.empty()){
int x =Q.front();
Q.pop();
siz[node[x].fa][0]+=siz[x][0];
siz[node[x].fa][1]+=siz[x][1];
if(--in[node[x].fa]==0){
Q.push(node[x].fa);
}
}
int mx = 0;
rep(i,1,n){
int len =s[i].size();
int now = 1;
int val = 0;
rep(j,0,len-1){
int c = s[i][j]-'a';
if(node[now].ch[c]){
now = node[now].ch[c];
if(siz[now][0]&&siz[now][1]){
val = j+1;
}
}
else{
break;
}
}
mx = max(mx,val);
}
printf("%d\n",mx);
}
int main(){
T=read();
while(T--){
n=read();
rep(i,1,n){
scanf("%s",p);
s[i].clear();
int len = strlen(p);
rep(j,0,len-1){
s[i]+=p[j];
}
}
m=read();
rep(i,1,m){
int l,r;
l=read(),r=read();
init();
last = 1;
for(int j=0,len=s[l].size();j<len;++j){
last = extend(s[l][j]-'a',last,0);
}
last = 1;
for(int j=0,len=s[r].size();j<len;++j){
last = extend(s[r][j]-'a',last,1);
}
solve();
}
}
return 0;
}