• 求两个字符串(数字串也是一样)是不是循环同构


    第一种方法是kmp:将一个数组复制一次,然后再用另一个进行匹配。

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    
    using namespace std;
    
    const int N = 200005;
    const int MOD = 360000;
    
    int a[N],b[N],c[2*N],d[N],f[N];
    
    void getFail(int n){
        f[0]=0;f[1]=0;
        for(int i=1;i<n;i++){
            int j=f[i];
            while(j&&d[i]!=d[j]) j=f[j];
            f[i+1] = d[i]==d[j]?j+1:0;
        }
    }
    
    bool kmp(int n)
    {
        getFail(n);
        int j =0;
        for(int i=0;i<2*n;i++){
            while(j&&d[j]!=c[i]) j=f[j];
            if(d[j]==c[i]) j++;
            if(j==n) return true;
        }
        return false;
    }
    
    void run()
    {
        int n;
        while(cin>>n)
        {
            for(int i=0;i<n;i++) cin>>a[i];
            for(int i=0;i<n;i++) cin>>b[i];
            sort(a,a+n);sort(b,b+n);
    
            for(int i=0;i<n-1;i++)
            {
                c[i]=(a[i+1]-a[i]+MOD)%MOD;
                c[n+i]=c[i];
                d[i]=(b[i+1]-b[i]+MOD)%MOD;
            }
            c[n-1]=(MOD-a[n-1]+a[0])%MOD;
            c[2*n-1]=c[n-1];
            d[n-1]=(MOD-b[n-1]+b[0])%MOD;
    
            //for(int i=0;i<2*n;i++) cout<<c[i]<<" ";cout<<endl;
            //for(int i=0;i<n;i++) cout<<d[i]<<" ";cout<<endl;
    
            if(kmp(n)) puts("possible");
            else puts("impossible");
    
        }
    }
    
    int main()
    {
        ios::sync_with_stdio(0);
        run();
        //cout << "Hello world!" << endl;
        return 0;
    }
    View Code

    第二种方法是最小表示法:分别求两个串的最小表示,再进行比较。

    #include <iostream>
    #include <algorithm>
    #include <cstdio>
    
    using namespace std;
    
    const int N = 200005;
    const int MOD = 360000;
    
    int a[N],b[N],c[N],d[N];
    
    int getminsub(int* a,int len)
    {
        int i=0,j=1,k=0;
        while(i<len&&j<len&&k<len)
        {
            if(k==len) break;
            if(i==j) j++;
            int ni=i+k,nj=j+k;
            if(ni>=len) ni-=len;
            if(nj>=len) nj-=len;
            if(a[ni]>a[nj])
            {
                i+=(k+1);
                k=0;
            }
            else if(a[ni]<a[nj])
            {
                j+=(k+1);
                k=0;
            }
            else k++;
        }
        return i;
    }
    
    void run()
    {
        int n;
        while(cin>>n)
        {
            for(int i=0;i<n;i++) cin>>a[i];
            for(int i=0;i<n;i++) cin>>b[i];
            sort(a,a+n);sort(b,b+n);
            for(int i=0;i<n-1;i++)
            {
                c[i]=(a[i+1]-a[i]+MOD)%MOD;
                d[i]=(b[i+1]-b[i]+MOD)%MOD;
            }
            c[n-1]=(MOD-a[n-1]+a[0])%MOD;
            d[n-1]=(MOD-b[n-1]+b[0])%MOD;
    
            //for(int i=0;i<n;i++) cout<<c[i]<<" ";cout<<endl;
            //for(int i=0;i<n;i++) cout<<d[i]<<" ";cout<<endl;
    
            int f=getminsub(c,n);
            int k=getminsub(d,n);
    
            //cout<<f<<" "<<k<<endl;
    
            int l=0;bool cp=true;
            while(l<n)
            {
                if(c[f]==d[k])
                {
                    l++;
                    f++;if(f==n) f=0;
                    k++;if(k==n) k=0;
                }
                else {cp=false;break;}
            }
    
            if(cp) puts("possible");
            else puts("impossible");
    
        }
    }
    
    int main()
    {
        run();
        //cout << "Hello world!" << endl;
        return 0;
    }
    View Code
  • 相关阅读:
    c++求最大公约数、最小公倍数
    五个简单的shell脚本
    微信小程序slot(一)
    小程序详解子传父
    小程序封装组件详解父传子
    小程序生命周期详解
    小程序之confirm-type改变键盘右下角的内容和input按钮详解
    小程序之按钮你不知道的v2
    小程序image图片缩小不变形
    小程序之navigator跳转方式
  • 原文地址:https://www.cnblogs.com/BugClearlove/p/4442860.html
Copyright © 2020-2023  润新知