ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

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

2022-09-12 03:30:09  阅读:165  来源: 互联网

标签:nnn ac 数一数 int mn 之积 cin 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 n∀1≤i≤n,求出∏j=1nf(si,sj)\prod_{j=1}^n {f(s_i,s_j)}∏j=1n​f(si​,sj​)。 由于答案很大,你只需要输出对 998244353 取模后的结果。

输入描述:

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

输出描述:

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

输入

复制
1
BALDRSKYKirishimaRain

输出

复制
1

备注:

1≤n≤1061 ≤ n ≤ 10^61≤n≤106,所有字符串的总长度不超过 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;
}

/*样例区


*/

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

 

标签:nnn,ac,数一数,int,mn,之积,cin,kmp,字符串
来源: https://www.cnblogs.com/er007/p/16685336.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有