版权声明: https://blog.csdn.net/weixin_39792252/article/details/82257211
题目:要求将前个字符放到后面字符串的后面形成一个新串,如果,和就放在一组,最后将每一组按照字典序排序,每一组的个数就是这组的一个标号。
思路1:将字符串复制一下,那么用字符串hash,只要维护之前有没有出现过就可以啦,但是非常卡时间!!!
字符串hash的常见方法:
*111111...... unsigned long long 相当于对取模
unsigned long long hash[maxn], p[maxn];
char s[maxn];
void Hash(int x) {
p[0] = 1;
h[0] = 0;
for(int i = 1; i <= x; i++) {
p[i] = p[i-1]*seed;
h[i] = h[i-1]*seed + s[i];
}
}
unsigned long long gethash(int l, int r) {
return h[r] - h[l-1]*p[r - l + 1];
}
*222222......single hash(一般seed取6-8位的素数,mod取1e9+7 || 1e9 + 9)
inline void Hash(int x) {
p[0] = 1;
h[0] = 0;
for(int i = 1; i <= x; i++) {
p[i] = (p[i-1]*seed)%mod;
h[i] = (h[i-1]*seed%mod + s[i]-'a')%mod;
}
}
inline ll gethash(int l, int r) {
return (h[r] - h[l-1]*p[r - l + 1]%mod + mod)%mod;
}
*333333......double hash(mod1取1e9+7 || mod2取1e9+9)
hash1[i] = (hash1[i-1]*p + idx(s[i]))%mod1;
hash2[i] = (hash2[i-1]*p + idx(s[i]))%mod2;
代码:
#include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
#include<unordered_map>
#include<algorithm>
#define ll long long
#define ull unsigned long long
#define inf 0x3f3f3f
#define seed 131
using namespace std;
const int maxn = 2e6+5;
int len;
char s[maxn];
ull p[maxn], h[maxn];
inline void Hash(int x) {
p[0] = 1;
h[0] = 0;
for(int i = 1; i <= x; i++)
{
p[i] = p[i-1]*seed;
h[i] = h[i-1]*seed + s[i];
}
}
inline ull gethash(int l, int r) {
return h[r] - h[l-1]*p[r - l + 1];
}
vector<int> v[maxn];
unordered_map<ull, int> mp;
int main()
{
//freopen("in.txt", "r", stdin);
while(scanf("%s", s+1) != EOF) {
len = strlen(s+1);
for(int i = 1; i <= len; i++) s[i+len] = s[i];
Hash(2*len);
int num = 0;
for(int i = 1; i <= len; i++) {
ull ans = gethash(i, i+len-1);
if(mp[ans] == 0) {
mp[ans] = ++num;
v[num].push_back(i-1);
} else {
v[mp[ans]].push_back(i-1);
}
}
printf("%d\n", num);
for(int i = 1; i <= num; i++)
{
printf("%d", v[i].size());
for(int j = 0; j < v[i].size(); j++) printf(" %d", v[i][j]);
printf("\n");
}
}
return 0;
}
第二种思路是:利用KMP的next数组求字符串的最小循环节,正确把握next数组的本质
具体暂时留坑吧。。。。
扫描二维码关注公众号,回复:
3127010 查看本文章
代码:
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e6+10;
char str[maxn];
int nex[maxn];
void get_next(int len) {
int j = -1;
nex[0] = -1;
for(int i = 1; i <= len; i++) {
while(j>-1&&str[j+1] != str[i]) j = nex[j];
if(str[j+1] == str[i]) j++;
nex[i] = j;
}
//for(int i = 0; i < len; i++) cout << nex[i] << endl;
}
int main(void) {
cin >> str;
int len = strlen(str);
get_next(len);
int x = len - nex[len-1] - 1;
if (len % x != 0) {
printf("%d\n", len);
for(int i = 0; i < len; i++) printf("1 %d\n", i);
}
else {
printf("%d\n", x);
for(int i = 0; i < x; i++) {
printf("%d", len / x);
for(int j = i; j < len; j += x) printf(" %d", j);
printf("\n");
}
}
return 0;
}