D.String Commutativity(2020强智杯)

题目链接:https://ac.nowcoder.com/acm/contest/9699/D

题目描述:

Bobo has n strings s1, ... , sn, and he would like to find the number of pairs i < j where si + sj = sj + si.
Note that a + b means the concatenation of the string a and b, i.e., writing the string a first, and the string b second.

翻译:

Bobo有n个字符串s1,…, sn,他想要找到si + sj = sj + si, i < j的配对数。
注意,a + b意味着字符串a和b的连接,也就是说,首先写入字符串a,然后写入字符串b。

输入描述:

The input consists of several test cases terminated by end-of-file.
The first line of each test case contains an integer n. The i-th of the following n lines contains a string si.
 · 1 ≤ n ≤ 105
 · |si| ≤ 106, si contains only lower case characters.
 · The sum of strings does not exceed 5×106

翻译:
输入由几个以文件结束符结束的测试用例组成。
每个测试用例的第一行包含一个整数n。接下来的n行中的第i行包含一个字符串si。
·1≤n≤105
·|si|≤106,si只包含小写字符。
·字符串的总和不超过5×106

输出描述:

For each test case, print an integer which denotes the result.

翻译:
对于每个测试用例,打印一个表示结果的整数。·字符串的总和不超过5×106

 

示例:

输入:
2
a
ab
2
ab
ab
3
a
aa
aaa

输出 :
0
1
3

 

题目分析:

题目要求给定两个字符串 si ,sj。要求si+sj==sj+si。

所以题目本质上是判断求字符串中去循环节之后两个字符串是否相等。

而判断字符串是否具有循环节,则可以通过求其next数组,并判断(len)%(len-next[len])==0是否成立。

注意,next数组需求到next[len]个,因为必须要知道最后一个字符是否有重复串。

 

本人垃圾代码:(没有ACC!,我也不知道为啥)

#pragma warning(disable:4996)
#include<bits/stdc++.h>
typedef long long ll;
const ll mod = 9999999967;
using namespace std;
namespace fastIO {
    inline void input(int& res) {
        char c = getchar();res = 0;int f = 1;
        while (!isdigit(c)) { f ^= c == '-'; c = getchar(); }
        while (isdigit(c)) { res = (res << 3) + (res << 1) + (c ^ 48);c = getchar(); }
        res = f ? res : -res;
    }
    inline ll qpow(ll a, ll b) {
        ll ans = 1, base = a;
        while (b) {
            if (b & 1) ans = (ans * base % mod + mod) % mod;
            base = (base * base % mod + mod) % mod;
            b >>= 1;
        }
        return ans;
    }
}
using namespace fastIO;
inline int get_next(string q)
{
    if (q.length() == 1)
        return 0;
    
    ll len = q.length();
    q.push_back('a');
    ll i = 0, j = -1;
    ll next[50000000];
    next[0] = -1;
    while (i < len)
    {
        if (j == -1 || q[i] == q[j])
        {
            ++i;++j;
            next[i] = j;
        }
        else
            j = next[j];
    }

    if (len % (len - next[len]) == 0)
        return next[len];
    else return -1;
}
inline bool judge(string p, string q)
{
    ll j = get_next(p);
    ll k = get_next(q);
    if (j != -1)
        p.erase(p.length() - j, p.length());
    if (k != -1)
        q.erase(q.length() - k, q.length());
    if (p.compare(q) == 0)
        return true;
    else
        return false;

}
int main()
{
    ios::sync_with_stdio(false);
    ll num;
    vector<string>a;
    string b;
    while (cin >> num)
    {
        getchar();
        for (ll z = 0;z < num;z++)
        {
            getline(cin, b);
            a.push_back(b);
        }
        if (num == 1)
        {
            cout << 0 << endl;
            a.clear();
            continue;
        }
        ll i = 0, j, ans = 0;
        for (i;i < num - 1;i++)
            for (j = i + 1;j <= num - 1;j++)
                if (judge(a[i], a[j]))
                    ans++;
        cout << ans << endl;
        ans = 0;
        a.clear();
    }
}

 

附上神仙代码:

#include <bits/stdc++.h>
typedef long long ll;
const ll mod = 9999999967;
using namespace std;
namespace fastIO {
    inline void input(int& res) {
        char c = getchar();res = 0;int f = 1;
        while (!isdigit(c)) { f ^= c == '-'; c = getchar(); }
        while (isdigit(c)) { res = (res << 3) + (res << 1) + (c ^ 48);c = getchar(); }
        res = f ? res : -res;
    }
    inline ll qpow(ll a, ll b) {
        ll ans = 1, base = a;
        while (b) {
            if (b & 1) ans = (ans * base % mod +mod )%mod;
            base = (base * base % mod + mod)%mod;
            b >>= 1;
        }
        return ans;
    }
}
using namespace fastIO;
const int N = 1e6 + 5;

int Case,n,len;
string s;
int nxt[N];

void solve(){
    map<string,int> vis;
    ll res = 0;
    for(int i=1;i<=n;i++){
        cin>>s;
        len =s.size();
        int t = len;
        int j=0,ans,k=-1;
        len=s.size();
        nxt[0]=-1;
        while(j<=len){
            if(k==-1||s[j]==s[k])
                nxt[++j]=++k;
            else
                k=nxt[k];
        }
        ans = len%(len-nxt[len])?1:len/(len-nxt[len]);
        s=s.substr(0,len/ans);
        res += vis[s]; 
        vis[s]++;
    }
    printf("%lld\n",res);
}

int main(){
    //init();
    Case=1;
    //scanf("%d",&Case);
    while(~scanf("%d",&n)){
        solve();
     }
    return 0;
}

神仙博客:https://blog.csdn.net/u011156006/article/details/110560702

 

 

具体为啥没有acc我不知道,日后总结(懒).......
如果有神仙知道为啥务必留言.
posted @ 2021-01-13 23:44  Carrout  阅读(154)  评论(0编辑  收藏  举报