B 数一数 kmp 字符串匹配数量之积

 链接:https://ac.nowcoder.com/acm/contest/27589/B
来源:牛客网

题目描述

s,ts,ts,t 为两个字符串,定义 f(s,t)=tf(s,t) = tf(s,t)=t 的子串中,与 sss 相等的串的个数。如 f("ac","acacac")=3f("ac","acacac")=3f("ac","acacac")=3 , f("bab","babab")=2f("bab","babab")=2f("bab","babab")=2。
现在给出 nnn 个字符串,第 iii 个字符串为 sis_isi。你需要对∀1≤i≤n\forall 1 \leq i \leq n1in,求出∏j=1nf(si,sj)\prod_{j=1}^n {f(s_i,s_j)}j=1nf(si,sj)。
由于答案很大,你只需要输出对 998244353 取模后的结果。

输入描述:

第一行一个整数 nnn。
接下来 nnn 行每行一个仅由英文字母构成的非空字符串,第 iii 个字符串代表 sis_isi

输出描述:

nnn 行,第 iii 行输出对 998244353 取模的结果。
示例1

输入

复制
1
BALDRSKYKirishimaRain

输出

复制
1

备注:

1≤n≤1061 ≤ n ≤ 10^61n106,所有字符串的总长度不超过 2×1062 \times10^62×106
 

分析:

由于长度长的字符串不可能是长度短的字符串的子串

所以只要找出长度最短的字符串,用它们来匹配其它所有字符串就可以了

 

//-------------------------代码----------------------------

#define int ll
const int N = 3e6+10;
int n,m;

string s[N];
int nxt[N];

void solve()
{
//    cin>>n>>m;
    cin>>n;
    int mn = 1e18;
    fo(i,1,n) {
        cin>>s[i];
        mn = min((int)s[i].size(),mn);
    }
    bool f = 1;
    bool first = 0;
    string tmp;
    set<int> q;
    fo(i,1,n) {
        if(s[i].size() == mn) {
            if(first == 0) {
                tmp = s[i];
            } else {
                if(tmp != s[i]) {
                    f = 0;
                    break;
                }
            }
            q.insert(i);
        }
    }
    
    if(!f) {
        fo(i,1,n) cout<<0<<'\n';
        return;
    }
    tmp = ' ' + tmp;
    fo(i,2,mn) {
        nxt[i] = nxt[i-1];
        while(nxt[i] && tmp[nxt[i] + 1] != tmp[i]) nxt[i] = nxt[nxt[i]];
        if(tmp[nxt[i] + 1] == tmp[i]) nxt[i] ++ ;
    }
    fo(i,1,mn) {
//         cout<<nxt[i]<<' '<<i<<endl;
    }
    ll ans = 1;
    
    fo(k,1,n) {
        if(q.count(k)) continue;
        int j = 1;
        string ss = s[k];
        int lens = ss.size();
        ss = ' ' + ss;
        ll d = 0;
        fo(i,1,lens) {
            while(j!=1 && ss[i] != tmp[j]) j = nxt[j-1] + 1;
            if(tmp[j] == ss[i]) j ++ ;
            if(j == mn + 1) {
                d ++ ;
                j = nxt[j-1] + 1;
            }
        }
        ans *= d;
        ans %= 998244353;
    }
    
    fo(i,1,n) {
        if(q.count(i)) {
            cout<<ans<<'\n';
        } else cout<<0<<'\n';
    }
}
void main_init() {}
signed main(){
    AC();clapping();TLE;
    cout<<fixed<<setprecision(12);
    main_init();
//  while(cin>>n,n)
//  while(cin>>n>>m,n,m)
//    int t;cin>>t;while(t -- )
    solve();
//    {solve(); }
    return 0;
}

/*样例区


*/

//------------------------------------------------------------

 

posted @ 2022-09-12 03:12  er007  阅读(24)  评论(0编辑  收藏  举报