zoukankan      html  css  js  c++  java
  • BZOJ 1398: Vijos1382寻找主人 Necklace(最小表示法)

    传送门

    解题思路

      最小表示法。首先对于判断是不是循环同构的串,直接扫一遍用哈希判即可。然后要输出字典序最小的就要用到最小表示法,首先可以把串复制一遍,这样的话就可以把串变成静态操作。如果对于两个位置(i,j),若他们(isim i+k-1)(jsim j+k-1)这些位置都两两相等,而(s[i+k]<s[j+k])的话。那么首先可以知道的是(j)这个位置一定不是最小表示的开头,还有一个性质就是(jsim j+k)这些位置也一定不是,因为(s[i+k]<s[j+k]),那么这些位置也一定有一个对应的(i_0),使得他们在(i+k)的位置依然不相等。所以用一个双指针扫,时间复杂度(O(n))

    代码

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<cstdlib>
    
    using namespace std;
    const int MAXN = 1000005;
    const int base = 666623333;
    typedef unsigned long long ULL;
    
    char s1[MAXN],s2[MAXN];
    ULL hsh1[MAXN<<1],hsh2[MAXN],poww[MAXN<<1];
    int ans,n;
    bool flag;
    
    inline bool check(int x){
    	return (hsh1[x+n-1]-hsh1[x-1]*poww[n])==(hsh2[n]-poww[n])?1:0;
    }
    
    int main(){
    	scanf("%s%s",s1+1,s2+1);
    	n=strlen(s1+1);
    	for(int i=1;i<=n;i++) s1[i+n]=s1[i];hsh1[0]=hsh2[0]=1;poww[0]=1;
    	for(int i=1;i<=(n<<1);i++) {hsh1[i]=hsh1[i-1]*base+s1[i]-'0'+1;poww[i]=poww[i-1]*base;}
    	for(int i=1;i<=n;i++) hsh2[i]=hsh2[i-1]*base+s2[i]-'0'+1;
    	for(int i=1;i<=n;i++) if(check(i)) {flag=1;break;}
    	if(!flag) {puts("No");return 0;}
    	puts("Yes");int l=1,r=2,k;
    	while(l<=n && r<=n) {
    		for(k=0;s1[l+k]==s1[r+k] && k<=n;k++);
    		if(k==n) break;
    		if(s1[l+k]<s1[r+k]) {r=r+k+1;r+=(r==l);}
    		else {l=l+k+1;l+=(l==r);}
    	}
    	ans=min(l,r);
    	for(int i=ans;i<=ans+n-1;i++) putchar(s1[i]);putchar('
    ');
    	return 0;
    }
    
  • 相关阅读:
    redis(lettuce)
    Dubbo与SSM整合(认证授权)步骤
    maven常用命令
    Dubbo(RPC框架)
    SpringCache
    mybatis(SSM整合)
    java设计模式-命令模式
    java设计模式-原型模式
    java设计模式-职责链模式
    java设计模式-建造者模式
  • 原文地址:https://www.cnblogs.com/sdfzsyq/p/9847757.html
Copyright © 2011-2022 走看看