gggyt  
没谁离不开谁

  题意:给你n个字符串,问你是否存在一个字符串可以从中找到其他n-1个字符串。

  思路:其实很简单,找到最长的那个字符串对他进行匹配,看是否能匹配到n-1个字符串。

  可以用AC自动机或者后缀自动机做,但是AC自动机用指针的话会MLE,但是我比赛的时候用自己的后缀自动机的板子T了!

  然后用了dalao的板子,还是我的板子不够优秀啊(┬_┬)

  AC自动机版:

#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<vector>
#include<cmath>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<algorithm>
using namespace std;
const int maxn=1e5+100;
const int maxm=50*10010;
const int SIGMA_SIZE=26;
int n;
char t[maxn],s[maxn];

struct AC
{
    int ch[maxm][26];
    int val[maxm];
    int fail[maxm],last[maxm];
    int sz;
    void clear(){memset(ch[0],0,sizeof(ch[0]));sz=1;}
    int idx(char x){return x-'a';}
    void insert(char *s)
    {
        int u=0;
        int n=strlen(s);
        for(int i=0;i<n;i++)
        {
            int c=idx(s[i]);
            if(!ch[u][c])
            {
                memset(ch[sz],0,sizeof(ch[sz]));
                val[sz]=0;
                ch[u][c]=sz++;
            }
            u=ch[u][c];
        }
        val[u]++;
    }
    void getfail()
    {
        queue<int> q;
        fail[0]=0;
        int u=0;
        for(int i=0;i<SIGMA_SIZE;i++)
        {
            u=ch[0][i];
            if(u){q.push(u);fail[u]=0;last[u]=0;}
        }
        while(!q.empty())
        {
            int r=q.front();q.pop();
            for(int i=0;i<SIGMA_SIZE;i++)
            {
                u=ch[r][i];
                if(!u){ch[r][i]=ch[fail[r]][i];continue;}
                q.push(u);
                int v=fail[r];
                while(v&&!ch[v][i])v=fail[v];
                fail[u]=ch[v][i];
                last[u]=val[fail[u]]?fail[u]:last[fail[u]];
            }
        }
    }
    int find(char *s)
    {
        int u=0,cnt=0;
        int n=strlen(s);
        for(int i=0;i<n;i++)
        {
            int c=idx(s[i]);
            u=ch[u][c];
            int temp=0;//必须赋初值为0,表示如果下面两个判断都不成立的时候while可以正常执行
            if(val[u])
                temp=u;
            else if(last[u])
                temp=last[u];
            while(temp)
            {
                cnt+=val[temp];
                val[temp]=0;
                temp=last[temp];
            }
        }
        return cnt;
    }
}tree;
string a[maxn];
void solve()
{
        scanf("%d",&n);
        tree.clear();
        int maxx=0, id=0;
        for(int i=1;i<=n;i++)
        {
            scanf("%s",t);
            tree.insert(t);
            int len=strlen(t);
            if (len>maxx) {
                maxx=len;
                id=i;
            }
            a[i]=string(t);
        }
        tree.getfail();
        int len=a[id].length();
        for (int i=0; i<len; i++)
            t[i]=a[id][i];
        int ans=tree.find(t);
        //printf("%d\n",ans);
        if (ans==n)  puts(t);
        else  puts("No");

}
int main() {
    int t = 1;
    //freopen("in.txt", "r", stdin);
    //freopen("out.txt", "w", stdout);
    scanf("%d", &t);
    while(t--)
        solve();
    return 0;
}

  后缀自动机:

/** @xigua */
#include <stdio.h>
#include <cmath>
#include <iostream>
#include <algorithm>
#include <vector>
#include <stack>
#include <cstring>
#include <queue>
#include <set>
#include <string>
#include <map>
#include <climits>
#define PI acos(-1)
#define rep(a,b,c) for(int (a)=(b); (a)<(c); ++(a))
#define drep(a,b,c) for(int (a)=(b); (a)>(c); --(a))
#define CLR(x) memset(x, 0, sizeof(x))
#define sf scanf
#define pf printf
using namespace std;
typedef long long ll;
typedef double db;
const int maxn = 1e5 + 1000;
const int ma = 1e5 + 1000;
const int mod = 1e9 + 7;
const int INF = 1e8 + 5;
const ll inf = 1e17 + 5;
const db eps = 1e-6;
const int MAXN = 2e5+1e3;
char pool[MAXN];

struct Str{
    int st, len;
}str[MAXN];
struct state {
    int len, pre, ch[26];
};
struct SAM {
    int sz, last;
    state st[MAXN];
    state& operator[] (int x) {
        return st[x];
    }
    void clear(int x) {
        CLR(st[x].ch);
    }
    void init() {
        sz=1, last=0;
        st[0].len=0, st[0].pre=-1;
        clear(0);
    }
    void add(int c) {
        int cur=sz++, p;
        clear(cur);
        st[cur].len=st[last].len+1;
        for(p=last; p!=-1&&!st[p].ch[c]; p=st[p].pre)
            st[p].ch[c]=cur;
        if(p==-1) st[cur].pre=0;
        else {
            int q=st[p].ch[c];
            if(st[q].len==st[p].len+1)
                st[cur].pre=q;
            else {
                int clone=sz++;
                st[clone]=st[q];
                st[clone].len=st[p].len+1;
                st[cur].pre=st[q].pre=clone;
                for(; p!=-1&&st[p].ch[c]==q; p=st[p].pre)
                    st[p].ch[c]=clone;
            }
        }
        last=cur;
    }
    int find(string t) {//查询lcs
        int now=0, l=0, ans=0;
        int len=t.length();
        for (int i=0; i<len; i++) {
            while(now&&!st[now].ch[t[i]-'a']) {
                now=st[now].pre;
                l=st[now].len;
            }
            if(st[now].ch[t[i]-'a']) {
                ++l;
                now=st[now].ch[t[i]-'a'];
            }
            ans=max(l, ans);
        }
        return ans;
    }
} sam;
string a[maxn];
bool check(int sel, int n) {
    for (int i=0; i<n; i++) {
        if (i!=sel) {
            if (sam.find(a[i])!=a[i].length())  return 0;
        }
    }
    return true;
}
char ans[maxn];
void solve() {
    int n;  scanf("%d", &n);
    str[0].st=0;
    int sel=0, maxx=0;
    for (int i=0; i<n; i++) {
        scanf("%s", pool);
        int len=strlen(pool);
        if (len>maxx)  {
            maxx=len;
            sel=i;
        }
        a[i]=string(pool);
    }
    sam.init();
    int len=a[sel].length();
    for (int i=0; i<len; i++)
        sam.add(a[sel][i]-'a');
    for (int i=0; i<len; i++)
        ans[i]=a[sel][i];
    if(check(sel,n)) {
        int l=a[sel].length();
        for (int i=0; i<len; i++)
            printf("%c", ans[i]);
            puts("");
    }
    else puts("No");
}
int main() {
    int t = 1, cas = 1;
    //freopen("in.txt", "r", stdin);
   // freopen("out.txt", "w", stdout);
    scanf("%d", &t);
    while(t--) {
       // printf("Case %d: ", cas++);
        solve();
    }
    return 0;
}

 

posted on 2017-09-18 18:16  gggyt  阅读(248)  评论(0编辑  收藏  举报