HDU6138 Fleet of the Eternal Throne

题意:让你找两个串最长公共子序列并且这两个最长公共子序列是某个串的前缀,让你求最长是多长
题解:用这些字符串建一个AC自动机,然后扔一个串进去看一下这个跑一边AC自动机,因为AC自动机匹配的是某个串的前缀所以可以把这些结点加进去用set维护一下,最后另外一个串再跑一遍AC自动看他经过的那些节点的前缀是否在set里面如果有就ans = max(v[ret],ans);
用v数组记录一下该结点是第几个前缀即可

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<queue>
#include<set>
#include<vector>
#include<string>
#define mes(s) memset(s,0,sizeof(s))
#define rec(i,a,n) for(i = a; i <= n; i++)
#define dec(i,a,n) for(i = n; i >= a; i--)
using namespace std;
const int mx = 1e5+10;
string s[mx];
set<int>st;
struct trie{
    int ch[mx][26];
    int v[mx];
    int f[mx];
    int sz;
    void init() {sz = 1,mes(ch[0]);}
    int idx(char c) { return c-'a';}
    void insert(string s){
        int len = s.length()-1;
        int u = 0,i;
        rec(i,0,len){
            int d = idx(s[i]);
            if(!ch[u][d]){
                mes(ch[sz]);
                v[sz] = i+1;
                ch[u][d] = sz++;
            }
            u = ch[u][d];
        }
    }
    void getfail(){
        int i,d,u;
        queue<int>q;
        rec(i,0,25){
            if(!ch[0][i])
                ch[0][i] = 0;
            else{
                f[ch[0][i]] = 0;
                q.push(ch[0][i]);
            }
        }
        while(!q.empty()){
            u = q.front();
            q.pop();
            rec(d,0,25){
                if(!ch[u][d]){
                    ch[u][d] = ch[f[u]][d];
                    continue;
                }
                f[ch[u][d]] = ch[f[u]][d];
                q.push(ch[u][d]);
            }
        }
    }
    int find(string a,string b){
        int len = a.length()-1,i;
        int u = 0;
        st.clear();
        int ans = 0;
        rec(i,0,len){
            int d = idx(a[i]);
            int ret = ch[u][d];
            while(ret){
             //   cout<<ret<<endl;
                st.insert(ret);
                ret = f[ret];
               // cout<<ret<<endl;
            }
            u = ch[u][d];
        }
        len = b.length()-1;
        u = 0;
        rec(i,0,len){
            int d = idx(b[i]);
            int ret = ch[u][d];
            while(ret){
                //cout<<ret<<endl;
                if(v[ret]>ans)
                    if(st.find(ret)!=st.end())
                            ans = v[ret];
                ret = f[ret];
            }
            u = ch[u][d];
        }
        return ans;
    }
}word;
int main(){
    int t,n,m;
    scanf("%d",&t);
    while(t--){
        word.init();
        scanf("%d",&n);
        for(int i = 1; i <= n; i++){
            cin>>s[i];
            word.insert(s[i]);
        }
        word.getfail();
        scanf("%d",&m);
        while(m--){
            int x,y;
            scanf("%d%d",&x,&y);
            printf("%d\n",word.find(s[x],s[y]));
        }
    }
    return 0;
}
©️2020 CSDN 皮肤主题: 编程工作室 设计师:CSDN官方博客 返回首页