标签:printf blog rac panel str rip amp nsis position
题意:
给你M和L,和一个字符串S。
要求找出S的子串中长度为L*M,并且可以分成M段,每段长L,并且M段都不相同的子串个数。
题解:
枚举起点
hash每个前缀串
那么一段子串的hash值就可以快速求出
twopointsO(n)求出长度M*L,,M个连续串是否相同
#include<iostream> #include<cstdio> #include<cstring> #include<string> #include<algorithm> #include<queue> #include<cmath> #include<map> using namespace std; #pragma comment(linker, "/STACK:102400000,102400000") #define ls i<<1 #define rs ls | 1 #define mid ((ll+rr)>>1) #define pii pair<int,int> #define MP make_pair typedef long long LL; typedef unsigned long long ULL; const long long INF = 1e18+1LL; const double pi = acos(-1.0); const int N = 5e5+10, MM = 1e3+20,inf = 2e9; const LL mod = 10000019ULL; inline LL read() { LL x=0,f=1;char ch=getchar(); while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘)f=-1;ch=getchar();} while(ch>=‘0‘&&ch<=‘9‘){x=x*10+ch-‘0‘;ch=getchar();} return x*f; } map<ULL,int > s; ULL bhas[N],has[N],sqr[N]; int M,L; char sa[N]; int vis[N]; int main() { sqr[0] = 1; for(int i = 1; i < N; ++i) sqr[i] = sqr[i-1] * mod; while(scanf("%d%d",&M,&L)!=EOF) { scanf("%s",sa+1); int n = strlen(sa+1); has[0] = 0; for(int i = 1; i <= n; ++i) { has[i] = has[i-1] * mod + sa[i] - ‘a‘ + 1; } int ans = 0; for(int i = 1; i <= L && i + M * L - 1 <= n; ++i) { int cnt = 0; s.clear(); int ll = 1,rr = 0; for(int j = i; j + L - 1 <= n; j += L) { int l = j, r = j + L - 1; ULL now = has[r] - has[l-1]*sqr[L]; if(s[now] == 0){ bhas[++rr] = now; if(rr - ll + 1 >= M)ans+=1; s[now] = 1; continue; } else { while(ll <= rr && bhas[ll]!=now) { s[bhas[ll++]] = 0; } s[bhas[ll++]] = 0; bhas[++rr] = now; if(rr - ll + 1 >= M)ans+=1; s[now] = 1; } } } printf("%d\n",ans); } return 0; }
标签:printf blog rac panel str rip amp nsis position
原文地址:http://www.cnblogs.com/zxhl/p/7226544.html