• 字符串最大/小表示法 字符串哈希


    字符串最大/小表示法

    例题 HDU 3374 String Problem()

    问题分析

    求 循环节用kmp 最小最大表示法直接套用模板
    最小/大表示法:开两个位置坐标 参数 i,j以及 跨度k(自己瞎起的名字,感觉很合适 噗...)
    利用while循环进行多级跳转比较(每一个位置为首字符串所有都比较一遍 i,j 各作为一个字符串的首位置 );还是看代码解析吧 _
    最好是自己对着代码推一遍例子(" ABCAACAAA ")立马就能明白了

    AC代码如下

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<cmath>
    using namespace std;
    const int maxx=1e6+10;
    int nexx[maxx],len;
    char s[maxx];
    //貌似scanf()输入字符串时只能用 char型数组
    //及时使用s.c_str()输入 也是转换成char[]型  
    void ge()//kmp 求next[]数组 
    {
    	int i=0,j=-1;
    	nexx[0]=-1;
    	while(i<len){
    		if(j==-1||s[i]==s[j]){
    			i++,j++;
    			nexx[i]=j;
    		}
    		else
    		j=nexx[j];
    	}
    }
    int min_max(int flag){//字符串最大最小表示法 
    	int i=0,j=1,k=0;//位置参数 i,j;跨度 k 
    	if(flag){ //判读 1最小表示法 0 最大 
    	while(i<len&&j<len&&k<len){//完全比较 
    	    int t =s[(i+k)%len]-s[(j+k)%len];//循环回去 
    	    if(t==0)//相等 跨度++,相当于2参数都分别后移一位 
              k++;
            else{ //存在大小差异 
    		    if(t>0)  //前者 i位置 大于 j
                    i+=k+1;//i变换为新的 最小下一位置 
                else
    	            j+=k+1;//i不变 j变换为较大一个下一位置 
    	        if(i==j)//i,j相等
    		        j++;
    		                
    		    k=0;//跨度重置->i,j延续 
    	    }
    	  }
    	  return min(i,j);
    	  //取在前面的 
    	}
    	else
    	{//同最小表示法 
    	while(i<len&&j<len&&k<len){
    	    int t =s[(i+k)%len]-s[(j+k)%len];
    	    if(t==0)
              k++;
            else{
    		    if(t>0)
                    j+=k+1;
                else
    	            i+=k+1;
    	        if(i==j)
    		        j++;
    		    k=0;
    	    }
    	  }
    	  return min(i,j);
    	}	 
    }
    int main()
    {
    	while(~scanf("%s",&s))
    	{
         len =strlen(s);
         ge();
    	 int x=len-nexx[len];
         int num=1;
         if(len%x==0)
         num=len/x;
         printf("%d %d %d %d
    ",min_max(1)+1,num,min_max(0)+1,num);
    	}
    	return 0;
    }
    

    例题 POJ 1200 Crazy Search

    解题思路: 将N个字符串分别转换成数字 然后按照 NC进制转换为 10进制

    运用了字符号串哈希

    然后开一个标记数组进行标记(判定唯一性) 这样大大缩短了 时间
    1600万-- 26个小写字母组合 再怎么 也不会太多
    但是 不知道 到底是怎么推出的公式来的 进制转换为10进制(很神奇~~)

    AC代码如下:

    #include<iostream>
    #include<algorithm>
    #include<cstdio>
    #include<cstring>
    #include<string.h>
    #include<set>
    using namespace std;
    const int maxn=16000006;
    char a[maxn];
    bool hash[maxn];
    int num[205];
    int main() 
    {
    	int n,m;
    	while(~scanf("%d%d",&n,&m))
    	{
    		memset(num,0,sizeof(num));
    		memset(hash,0,sizeof(hash));
    		scanf("%s",a);
    		int len=strlen(a);
    		int cnt=0;
    		for(int i=0;i<len;i++)
    		if(!num[a[i]])
    		num[a[i]]=cnt++;
    		int ans=0;
    		for(int i=0;i<=len-n;i++)
    		{
    			int sum=0;
    			for(int j=i;j<=i+n-1;j++)
    			sum=sum*m+num[a[j]];
    			if(!hash[sum])
    			{
    				ans++;
    				hash[sum]=1;
    			}
    		}
    		cout<<ans<<endl;
    	}
    	 return 0;
    }
    
  • 相关阅读:
    Java+TestNG+Maven+Excel+IDEA接口自动化入门(二)Get方法
    java8新特性lambda和Stream新手springboot案例2020年新版
    h2数据库作为内存型与springboot+mybatis的案例
    分布式远程调用SpringCloud-Feign的两种具体操作方式(精华)
    携程Apollo简单入门教程这一篇就够了
    【Linux系列一】安装JDK
    【SVN系列一】更新失败
    Centos7配置桥接网络
    Vm虚拟机最小化安装linux并配置NAT网络连接(全图)
    python 函数传递
  • 原文地址:https://www.cnblogs.com/maxv/p/11606004.html
Copyright © 2020-2023  润新知