HDU - 5069
求后缀与前缀的最大匹配长度
我写的很暴力
首先对于前一个字符串,直接匹配到末尾,其实接下来就是求\(fail\)树上的这段前缀上的每一个点与后一个串在\(trie\)树上的位置的最长公共前缀长度
我的做法是:将\(trie\)树树剖,依次访问\(fail\)树上的每一个节点回答询问
访问\(fail\)树上的节点前缀时就可以直接通过每经过一个点就++
对于这一段前缀的一个询问串x,令其在\(trie\)树上的末尾节点为y,我们就是找到所有的节点最深的在\(y\)对应的\(trie\)树前缀上的位置,这里我直接树剖加二分实现了
int n,m;
string s[N];
const int SIZE=N;
int End[N];
int trie[N][26],fail[N],cnt;
void clear(){
memset(trie,0,sizeof trie);
cnt=0;
}
int Insert(string &s){
int p=0;
rep(i,0,s.size()-1) {
int x=s[i]-'A';
if(!trie[p][x]) trie[p][x]=++cnt;
p=trie[p][x];
}
return p;
}
struct Graph{
struct Edge{
int to,nxt;
}e[SIZE];
int head[N],ecnt;
void AddEdge(int u,int v){
e[++ecnt].to=v;e[ecnt].nxt=head[u];
head[u]=ecnt;
}
void clear(){
memset(head,0,sizeof head);
ecnt=0;
}
}G;
int dep[N];
int sz[N],son[N],top[N],fa[N];
void dfs1(int u){
sz[u]=1,son[u]=-1;
rep(i,0,25) {
int v=trie[u][i];
if(!v) continue;
dep[v]=dep[u]+1;
fa[v]=u;
dfs1(v);
sz[u]+=sz[v];
if(son[u]==-1||sz[v]>sz[son[u]]) son[u]=v;
}
}
int L[N],R[N],dfn,id[N];
void dfs2(int u,int t){
top[u]=t;
id[L[u]=++dfn]=u;
if(~son[u]) dfs2(son[u],t);
rep(i,0,25) {
int v=trie[u][i];
if(!v||v==son[u]) continue;
dfs2(v,v);
}
R[u]=dfn;
}
void Build(){
static queue <int> que;
dfn=0;G.clear();
fa[0]=-1,dfs1(0);dfs2(0,0);
rep(i,0,25) if(trie[0][i]) {
que.push(trie[0][i]);
fail[trie[0][i]]=0;
}
while(!que.empty()){
int u=que.front(); que.pop();
G.AddEdge(fail[u],u);
rep(i,0,25) {
int &v=trie[u][i];
if(v) {
que.push(v);
fail[v]=trie[fail[u]][i];
} else v=trie[fail[u]][i];
}
}
}
vector <pair<int,int> > Q[N];
int sum[N];
void Add(int p,int x){
while(p<=dfn) sum[p]+=x,p+=p&-p;
}
int Que(int p){
int res=0;
while(p) res+=sum[p],p-=p&-p;
return res;
}
int Ans[N];
void dfs_getans(int u){
Add(L[u],1);
rep(i,0,Q[u].size()-1) {
int x=Q[u][i].first,qid=Q[u][i].second;
while(~x) {
int t=Que(L[x])-Que(L[top[x]]-1);
if(t) {//找到一个++的节点
int p=0;
t+=Que(L[top[x]]-1);
drep(j,16,0) if( (p+(1<<j)<L[x]) && sum[p+(1<<j)]<t) t-=sum[p+=(1<<j)];
p++;
Ans[qid]=dep[id[p]];
break;//二分这个节点的位置
}
x=fa[top[x]];
}
}
vector <pair<int,int> > tmp;
swap(tmp,Q[u]);
for(int i=G.head[u];i;i=G.e[i].nxt) {
int v=G.e[i].to;
dfs_getans(v);
}
Add(L[u],-1);
}
bool ed;
int main(){
ios::sync_with_stdio(false);
while(cin>>n>>m) {
clear();
rep(i,1,n) {
cin>>s[i];
End[i]=Insert(s[i]);
}
Build();
rep(i,1,m) {
int x=rd(),y=rd();
x=End[x],y=End[y];
Q[x].push_back(make_pair(y,i));
}
dfs_getans(0);
rep(i,1,m) printf("%d\n",Ans[i]);
}
}