• 博客园logo
  • 会员
  • 众包
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • HarmonyOS
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录
mhy12345
博客园    首页    新随笔    联系   管理    订阅  订阅

Contest 20140928 密碼破譯 字符串hash

  題意:詢問字符串指定區間循環節個數。

  解法:有循環節長度a的字符串s[x,y]的性質:s[x,y-a]==s[x+a,y]由此寫一個雙hash就行了。

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<ctime>
#include<cmath>
#include<algorithm>
#include<set>
#include<map>
#include<vector>
#include<string>
#include<queue>
using namespace std;
#ifdef WIN32
#define LL "%I64d"
#else
#define LL "%lld"
#endif
#define MAXN 1100000
#define MAXV MAXN*2
#define MAXE MAXV*2
#define INF 0x3f3f3f3f
#define INFL 0x3f3f3f3f3f3f3f3fLL
#define PROB "password"
#define _a 29
#define _b 131
#define mod 1000000007
typedef unsigned long long qword;
inline int nextInt()
{
        char ch;
        int x=0;
        bool flag=false;
        do
                ch=getchar(),flag=(ch=='-')?true:flag;
        while(ch<'0'||ch>'9');
        do x=x*10+ch-'0';
        while (ch=getchar(),ch<='9' && ch>='0');
        return x*(flag?-1:1);
}

int n,m;
char str[MAXN];
pair<qword,qword> hs[MAXN];
bool pflag[MAXN];
int prime[MAXN],topp=-1;
qword pow_a[MAXN];
qword pow_b[MAXN];
void init()
{
        int i,j;
        for (i=2;i*i<MAXN;i++)
        {
                if (!pflag[i])
                        prime[++topp]=i;
                for (j=0;j<=topp && i*prime[j]<MAXN;j++)
                {
                        pflag[i*prime[j]]=true;
                        if (i%prime[j]==0)break;
                }
        }
        pow_a[0]=1;
        pow_b[0]=1;
        for (i=1;i<MAXN;i++)
                pow_a[i]=pow_a[i-1]*_a%mod,
                        pow_b[i]=pow_b[i-1]*_b;
}
pair<qword,qword> hash(int x,int y)
{
        pair<qword,qword> ret;
        ret.first=((hs[x].first+mod-hs[y+1].first*pow_a[(y+1)-x]%mod)%mod+mod)%mod;/*Attention*/
        ret.second=hs[x].second-hs[y+1].second*pow_b[(y+1)-x];
        return ret;
}
int check(int x,int y)
{
        int ret=1;
        int len=(y-x+1);
        int lo=len;
        int a,i;
        for (i=0;i<=topp && prime[i]*prime[i]<=len;i++)
        {
                if (len%prime[i]==0)
                {
                        a=1;
                        while (len%prime[i]==0)
                        {
                                len/=prime[i];
                                a*=prime[i];
                                if (hash(x,y-lo/a)==hash(x+lo/a,y))
                                {
                                        ret*=prime[i];
                                }
                        }
                }
        }
        if (len>1)
        {
                a=len;
                if (hash(x,y-lo/a)==hash(x+lo/a,y))
                {
                        ret*=a;
                }
        }
        return ret;
}

int main()
{
        freopen(PROB".in","r",stdin);
        //freopen(PROB".out","w",stdout);
        int i,j,k;
        int x,y,z;
        int ans;
        init();
        scanf("%d\n",&n);
        fgets(str,sizeof(str),stdin);
        hs[n]=make_pair(1,1);
        for (i=n-1;i>=0;i--)
        {
                hs[i].first=hs[i+1].first*_a%mod+str[i]-'a'+1;
                hs[i].second=hs[i+1].second*_b+str[i]-'a'+1;
        }
//        pr3=hash(5,5);
        scanf("%d",&m);
        for (i=0;i<m;i++)
        {
                scanf("%d%d",&x,&y);
                x--;y--;
                printf("%d\n",(y-x+1)/check(x,y));
        }
        return 0;
}

 

by mhy12345(http://www.cnblogs.com/mhy12345/) 未经允许请勿转载

本博客已停用,新博客地址:http://mhy12345.xyz

posted @ 2014-09-29 15:46  mhy12345  阅读(162)  评论(0)    收藏  举报
刷新页面返回顶部
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3