@jason-fan
2021-04-26T14:25:27.000000Z
字数 17027
阅读 178
CODE
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 55;
const int mod = 1019260817;
const int bs = 10007;
int n, a[N][N], b[N][N];
set<ll> vs[N];
ll row[N][N], hsh[N][N][N], pw[N];
ll calc(int c, int l, int r) {
return (row[c][r] - row[c][l - 1] * pw[r - l + 1] % mod + mod) % mod;
}
void inithash(int(*a)[N]) {
pw[0] = 1; for (int i = 1; i <= n; ++i) pw[i] = pw[i - 1] * bs % mod;
for (int i = 1; i <= n; ++i) for (int j = 1; j <= n; ++j)
row[i][j] = ((ll)row[i][j - 1] * bs + a[i][j]) % mod;
for (int i = 1; i <= n; ++i) {
for (int j = 1; j <= n; ++j) { // (i,j)
for (int k = 1; max(i, j) + k - 1 <= n; ++k) {
hsh[i][j][k] = 0;
for (int p = 1; p <= k; ++p)
hsh[i][j][k] = (hsh[i][j][k] * pw[k] + calc(i + p - 1, j, j + k - 1)) % mod;
}
}
}
}
int main() {
scanf("%d", &n);
for (int i = 1;i <= n;++i) for (int j = 1;j <= n;++j) scanf("%d", &a[i][j]);
for (int i = 1;i <= n;++i) for (int j = 1;j <= n;++j) scanf("%d", &b[i][j]);
inithash(a);
for (int i = 1; i <= n; ++i) for (int j = 1; j <= n; ++j)
for (int k = 1; min(i, j) + k - 1 <= n; ++k) vs[k].insert(hsh[i][j][k]);
inithash(b);
for (int k = n; k >= 1; --k)
for (int i = 1; i + k - 1 <= n; ++i)
for (int j = 1; j + k - 1 <= n; ++j) if (vs[k].count(hsh[i][j][k]))
{printf("%d\n", k); return 0;}
puts("0");
return 0;
}
#include <bits/stdc++.h>
template<typename _Tp>
inline void red(_Tp& x) {
x = 0;bool fg = 0;char ch = getchar();
while (ch < '0' || ch>'9') { if (ch == '-') fg ^= 1;ch = getchar(); }
while (ch >= '0' && ch <= '9') x = (x << 1) + (x << 3) + (_Tp)(ch ^ 48), ch = getchar();
if (fg) x = -x;
}
template <typename _Tp, typename... Args>void red(_Tp& t, Args &... args) { red(t);red(args...); }
using namespace std;
typedef long long ll;
const int mod = 1019260817;
const int N = 110;
const int base = 97;
int head[N], fa[N], pnt[N], nxt[N], E;
int m, n, siz[N], rt1, rt2;
ll hah[N], pw[N];
pair<ll, ll> Hash[N];
vector<int> e[N];
void init() {
for (int i = 1;i <= n;++i) e[i].clear();
rt1 = rt2 = -1;
}
void dfs(int u, int f = 0, int dep = 1) {
siz[u] = 1; hah[u] = dep;
for (int i = 0, v;i < e[u].size();++i) {
v = e[u][i]; if (v == f) continue;
dfs(v, u, dep + 1);
siz[u] += siz[v];
}
sort(e[u].begin(), e[u].end(), [](int x, int y) {
return hah[x] < hah[y];
});
for (int i = 0, v;i < e[u].size();++i) {
v = e[u][i]; if (v == f) continue;
hah[u] = (hah[u] * pw[siz[v]] + hah[v]) % mod;
}
}
void getroot(int u, int f = 0) {
assert(u != 0);
siz[u] = 1; int mxsiz = 0;
for (int i = 0, v;i < e[u].size();++i) {
v = e[u][i]; if (v == f) continue;
getroot(v, u); siz[u] += siz[v];
mxsiz = max(mxsiz, siz[v]);
}
mxsiz = max(mxsiz, n - siz[u]);
if (mxsiz <= n / 2) {
if (rt1 == -1) rt1 = u;
else rt2 = u;
}
}
int main() {
red(m);
pw[0] = 1; for (int i = 1;i < N;++i) pw[i] = pw[i - 1] * base % mod;
for (int t = 1;t <= m;++t) {
init(); red(n);
for (int i = 1;i <= n;++i) {
red(fa[i]);
if (fa[i] != 0) {
e[fa[i]].push_back(i);
e[i].push_back(fa[i]);
}
}
getroot(1);
dfs(rt1); Hash[t].first = hah[rt1];
if (rt2 == -1) Hash[t].second = hah[rt1];
else {
dfs(rt2); Hash[t].second = hah[rt2];
if (Hash[t].first > Hash[t].second)
swap(Hash[t].first, Hash[t].second);
}
}
for (int t = 1;t <= m;++t) {
for (int i = 1;i <= m;++i) {
if (Hash[t] == Hash[i]) {
printf("%d\n", i);
break;
}
}
}
return 0;
}
#include <bits/stdc++.h>
#define fi first
#define se second
using namespace std;
typedef long long ll;
typedef pair<ll, ll> pll;
typedef unsigned long long ull;
const int N = 100010;
namespace strhash {
const int p1 = 1019260817;
const int p2 = 1019260819;
const int bs = 233;
pll pw[N], f[N];
pll operator*(pll a, ll b) { return pll(a.fi * b % p1, a.se * b % p2); }
pll operator+(pll a, ll b) { return pll((a.fi + b) % p1, (a.se + b) % p2); }
pll operator-(pll a, pll b) { return pll((a.fi - b.fi + p1) % p1, (a.se - b.se + p2) % p2); }
pll operator*(pll a, pll b) { return pll(a.fi * b.fi % p1, a.se * b.se % p2); }
void init(char* S, int n) {
pw[0] = pll{ 1,1 };
for (int i = 1;i <= n;++i) {
f[i] = (f[i - 1] * bs + (S[i] - 'a' + 1));
pw[i] = pw[i - 1] * bs;
}
}
ull gethash(int l, int r) {
pll a = f[r] - f[l - 1] * pw[r - l + 1];
return (ull)a.fi << 32 | (ull)a.se;
}
}
using strhash::init;using strhash::gethash;
int n, len[10];
char str[10][N];
struct my_hash {
static ull mix64(ull x) {
x += 0x9e3779b97f4a7c15;
x = (x ^ (x >> 30)) * 0xbf58476d1ce4e5b9;
x = (x ^ (x >> 27)) * 0x94d049bb133111eb;
return x ^ (x >> 31);
}
size_t operator()(ull x) const { return mix64(x); }
};
unordered_set<ull, my_hash> S1, S2;
bool check(int l) {
init(str[0], len[0]);
S1.clear();S2.clear();
for (int i = 1;i + l - 1 <= len[0];++i) {
S1.insert(gethash(i, i + l - 1));
}
for (int i = 1;i < n;++i) {
if (S1.empty()) return false;
init(str[i], len[i]);
for (int j = 1;j + l - 1 <= len[i];++j) {
ull mask = gethash(j, j + l - 1);
if (S1.find(mask) != S1.end()) {
S2.insert(mask);
S1.erase(mask);
}
}
S1.clear();swap(S1, S2);
}
return !S1.empty();
}
int main() {
while (scanf("%s", str[n] + 1) != EOF) {
len[n] = strlen(str[n] + 1);
++n;
}
int L = 0, R = *min_element(len, len + n), M, ans;
while (L <= R) {
M = (L + R) >> 1;
if (check(M)) ans = M, L = M + 1;
else R = M - 1;
}
cout << ans << endl;
return 0;
}
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 100010;
const int p1 = 1019260817;
const int p2 = 1019260819;
const int bs = 125641;
int a[N][6], n, k, C[7][7];
struct Hash_map {
static const int MAX_SIZE = 200010, M = 1627361;
struct data {
int nxt;
ll key, value;
} e[MAX_SIZE];
int head[M], size;
inline int f(ll key) { return key % M; } // 哈希函数
ll& operator[](const ll& key) {
int ky = f(key);
for (int i = head[ky]; i != -1; i = e[i].nxt)
if (e[i].key == key) return e[i].value;
return e[++size] = data{ head[ky], key, 0 }, head[ky] = size, e[size].value;
}
void clear() {
memset(head, -1, sizeof(head));
size = 0;
}
Hash_map() { clear(); }
};
Hash_map ct;
ll calc(int mask) {
ct.clear(); ll res = 0;
for (int i = 1;i <= n;++i) {
ll h1 = 0, h2 = 0;
for (int p = 0;p < 6;++p) if ((mask >> p) & 1) {
h1 = (h1 * bs + a[i][p]) % p1;
h2 = (h2 * bs + a[i][p]) % p2;
}
res += ct[h1 * h2]++;
}
return res;
}
int main() {
scanf("%d%d", &n, &k);
for (int i = 1;i <= n;++i) for (int j = 0;j < 6;++j) scanf("%d", &a[i][j]);
C[0][0] = 1;
for (int i = 1;i <= 6;++i) {
C[i][0] = 1;
for (int j = 1;j <= i;++j) C[i][j] = C[i - 1][j - 1] + C[i - 1][j];
}
ll ans = 0;
for (int mask = 0;mask < (1 << 6);++mask) {
int ct = 0; for (int x = mask;x;x -= x & -x) ++ct;
if (ct < k) continue;
ll tmp = calc(mask) * C[ct][k];
if ((ct - k) & 1) ans -= tmp;
else ans += tmp;
}
printf("%lld\n", ans);
return 0;
}
#include <bits/stdc++.h>
#define fi first
#define se second
using namespace std;
typedef long long ll;
const int N = 100010;
const int mod = 998244353;
inline ll Mod(ll x) {return x < mod ? x : x % mod;}
typedef pair<ll, ll> pll;
const int p1 = 1019260817; // 双模 hash
const int p2 = 1019260819;
const int c = 517666;
pll operator*(const pll &a, const ll &b) {return pll(a.fi * b % p1, a.se * b % p2);}
pll operator*(const pll &a, const pll &b) {return pll(a.fi * b.fi % p1, a.se * b.se % p2);}
pll operator+(const pll &a, const ll &b) {return pll((a.fi + b) % p1, (a.se + b) % p2);}
pll operator-(const pll &a, const pll &b) {return pll((a.fi - b.fi + p1) % p1, (a.se - b.se + p2) % p2);}
pll operator+(const pll &a, const pll &b) {return pll((a.fi + b.fi) % p1, (a.se + b.se) % p2);}
ll fac[N], ifac[N], inv[N], pr[N];
bool v[2000000];int tot;
void init(int n) {
fac[0] = inv[0] = inv[1] = ifac[0] = ifac[1] = 1;
for (int i = 1; i <= n; ++i) fac[i] = Mod(fac[i - 1] * i);
for (int i = 2; i <= n; ++i) inv[i] = Mod((mod - mod / i) * inv[mod % i]);
for (int i = 2; i <= n; ++i) ifac[i] = Mod(inv[i] * ifac[i - 1]);
for (int i = 2; tot < n; ++i) {
if(!v[i]) pr[++tot] = i;
for (int j = 1; j <= tot && pr[j] * i < 2e6; ++j) {
v[i * pr[j]] = 1;
if(i % pr[j] == 0) break;
}
}
srand(time(0));
random_shuffle(pr + 1, pr + tot + 1);
}
vector<int> e[N];
int t, n, siz[N];
ll f[N], g[N]; // f[u]: (以 1 为根)遍历 u 子树本质不同括号序列方案数 ; g[u] 以 u 为根
pll fh[N], gh[N]; // fh[u]: (以 1 为根) u 子树哈希值 ; gh[u] 以 u 为根
map<pll, int> ct[N]; // 统计 u 子树某哈希值出现次数
ll qpow(ll a, ll b = mod - 2) {
ll r = 1;
for ( ; b; b>>=1, a = Mod(a * a)) if(b & 1) r = Mod(r * a);
return r;
}
void dfs1(int u, int fa) {
ct[u].clear();
f[u] = fac[e[u].size() - (u != 1)];
fh[u] = pll(0, 0); siz[u] = 1;
for(auto &&v : e[u]) if(v != fa) {
dfs1(v, u);
fh[u] = fh[u] + fh[v] * pr[siz[v]];
f[u] = Mod(f[u] * f[v]);
siz[u] += siz[v];
}
sort(e[u].begin(), e[u].end(), [](int x, int y) {return fh[x] < fh[y];});
pll pre(-1, -1); int cnt = 0;
for(auto &&v : e[u]) if(v != fa) {
if(pre == fh[v]) f[u] = Mod(f[u] * inv[++cnt]);
else {
if(pre.fi != -1) ct[u][pre] = cnt;
cnt = 1, pre = fh[v];
}
}
if(pre.fi != -1) ct[u][pre] = cnt;
fh[u] = fh[u] + c;
}
void dfs2(int u, int fa, pll cur, ll now) {
// 换根DP : cur 为父亲方向哈希值, now 为父亲方向 f
g[u] = Mod(f[u] * now);
gh[u] = fh[u] + cur * pr[n - siz[u]];
if(u != 1) {
g[u] = Mod(Mod(g[u] * e[u].size()));
g[u] = Mod(g[u] * inv[++ct[u][cur]]);
}
for(auto &&v : e[u]) if(v != fa) {
pll _cur = fh[u] - fh[v] * pr[siz[v]] + cur * pr[n - siz[u]];
ll _now = Mod(Mod(g[u] * inv[e[u].size()]) * qpow(f[v]));
_now = Mod(_now * ct[u][fh[v]]);
dfs2(v, u, _cur, _now);
}
}
void rmain() {
scanf("%d", &n);
for (int i = 1; i <= n; ++i) e[i].clear();
for (int i = 1; i < n; ++i) {
int u, v; scanf("%d%d", &u, &v);
e[u].push_back(v); e[v].push_back(u);
}
dfs1(1, 0);
dfs2(1, 0, pll(0, 0), 1);
ct[0].clear();
ll ans = 0;
for (int i = 1; i <= n; ++i) {
if(ct[0].count(gh[i])) continue;
ct[0][gh[i]] = 1;
ans = Mod(ans + g[i]);
}
printf("%lld\n",ans);
}
int main() {
init(N - 1);
scanf("%d", &t);
while(t--) rmain();
return 0;
}
#include <bits/stdc++.h>
#define fi first
#define se second
#define ls (x<<1)
#define rs (x<<1|1)
#define mid ((l+r)>>1)
using namespace std;
const int N = 100010;
int n,m,q; char s[N];
typedef long long ll;
typedef pair<ll,ll> pll;
const int p1 = 1019260817; // 双模 hash
const int p2 = 1019260819;
const int bs = 125641; // 基数
pll operator*(const pll &a,const ll &b) {return pll(a.fi * b % p1, a.se * b % p2);}
pll operator*(const pll &a,const pll &b) {return pll(a.fi * b.fi % p1, a.se * b.se % p2);}
pll operator+(const pll &a,const ll &b) {return pll((a.fi + b) % p1, (a.se + b) % p2);}
pll operator-(const pll &a,const pll &b) {return pll((a.fi - b.fi + p1) % p1, (a.se - b.se + p2) % p2);}
pll operator+(const pll &a,const pll &b) {return pll((a.fi + b.fi) % p1, (a.se + b.se) % p2);}
pll pw[N],pws[N]; // pw[i] = bs ^ i
void init(int n) {
pw[0] = {0, 0};
for (int i = 1; i <= n; ++i) pw[i] = pw[i - 1] * bs;
}
struct dat {
pll f; // 哈希值
int len; // 串长
dat() { f = {0, 0}; len = 0; }
dat(const pll &_f,const int &_len) { f = _f; len = _len; }
};
dat operator*(const dat &a,const dat &b) {
return dat(a.f * pw[b.len] + b.f, a.len + b.len);
}
dat D[N<<2]; int tag[N<<2];
ostream &operator<<(ostream &out,const dat &a) {
return out<<"("<<a.f.first<<", "<<a.f.second<<", l="<<a.len<<") ";
}
void pushup(int x) {D[x]=D[ls]*D[rs];}
void build(int l=1,int r=n,int x=1) {
tag[x]=-1;
if(l==r) {D[x]=dat({s[l]-'0',s[l]-'0'},1);return ;}
build(l,mid,ls);build(mid+1,r,rs);
pushup(x);
}
void seteq(int x,int vl) { tag[x]=vl; D[x].f=pws[D[x].len-1]*vl; }
void pushdown(int x) {
if(tag[x]!=-1) {
seteq(ls,tag[x]); seteq(rs,tag[x]);
tag[x]=-1;
}
}
void modify(int L,int R,int vl,int l=1,int r=n,int x=1) {
if(L<=l&&r<=R) return seteq(x,vl);
pushdown(x);
if(L<=mid) modify(L,R,vl,l,mid,ls);
if(R>mid) modify(L,R,vl,mid+1,r,rs);
pushup(x);
}
dat query(int L,int R,int l=1,int r=n,int x=1) {
if(L>R) return dat();
if(L<=l&&r<=R) return D[x];
pushdown(x); dat ret;
if(L<=mid) ret=query(L,R,l,mid,ls);
if(R>mid) ret=ret*query(L,R,mid+1,r,rs);
return ret;
}
int main() {
scanf("%d%d%d",&n,&m,&q);q+=m;
scanf("%s",s+1);
pws[0]=pw[0]={1,1};
for(int i=1;i<=n;++i) {
pw[i]=pw[i-1]*bs;
pws[i]=pws[i-1]+pw[i];
}
build();
while(q--) {
int op,l,r,x;
scanf("%d%d%d%d",&op,&l,&r,&x);
if(op==1) {
modify(l,r,x);
}else {
dat a=query(l+x,r),b=query(l,r-x);
// printf("[%d,%d] [%d,%d]\n",l+x,r,l,r-x);
// cerr<<a<<" "<<b<<endl;
if(a.f==b.f) puts("YES");
else puts("NO");
}
}
return 0;
}
#include <bits/stdc++.h>
#define fi first
#define se second
template<typename _Tp>
inline void read(_Tp& x) {
x = 0;bool fg = 0;char ch = getchar();
while (ch < '0' || ch>'9') { if (ch == '-') fg ^= 1;ch = getchar(); }
while (ch >= '0' && ch <= '9') x = (x << 1) + (x << 3) + (_Tp)(ch ^ 48), ch = getchar();
if (fg) x = -x;
}
template<typename _Tp, typename... Args>void read(_Tp& t, Args &... args) { read(t);read(args...); }
using namespace std;
typedef long long ll;
const int N = 100010;
const int M = 500010;
int head[N], pnt[M << 1], nxt[M << 1], E;
int n, m, P[N], PP[N], w[N];
void adde(int u, int v) {
E++;pnt[E] = v;nxt[E] = head[u];head[u] = E;
}
namespace seq_Hash {
typedef long long ll;
typedef pair<ll, ll> pll;
const int p1 = 1019260817;
const int p2 = 1019260819;
const int bs = 10007;
pll operator*(const pll& a, const ll& b) { return pll(a.fi * b % p1, a.se * b % p2); }
pll operator*(const pll& a, const pll& b) { return pll(a.fi * b.fi % p1, a.se * b.se % p2); }
pll operator+(const pll& a, const ll& b) { return pll((a.fi + b) % p1, (a.se + b) % p2); }
pll operator-(const pll& a, const pll& b) { return pll((a.fi - b.fi + p1) % p1, (a.se - b.se + p2) % p2); }
pll operator+(const pll& a, const pll& b) { return pll((a.fi + b.fi) % p1, (a.se + b.se) % p2); }
pll pw[N];
void init(int n) {
pw[0] = { 1, 1 };
for (int i = 1; i <= n; ++i) pw[i] = pw[i - 1] * bs;
}
struct dat {
pll f; int len;
dat() { f = { 0,0 };len = 0; }
dat(const pll& _f, const int& _len) { f = _f; len = _len; }
};
dat operator*(const dat& a, const dat& b) {
return dat(a.f * pw[b.len] + b.f, a.len + b.len);
}
ostream& operator<<(ostream& out, const dat& a) {
return out << "dat{ (" << a.f.first << ", " << a.f.second << "), l=" << a.len << " } ";
}
}using namespace seq_Hash;
namespace segt {
#define ls(p) t[p].l
#define rs(p) t[p].r
#define mid ((l+r)>>1)
struct node {
int l, r; dat d;
}t[N * 30];
int sz, root;
int newnode() { ++sz;t[sz] = { 0,0,dat() }; return sz; }
void pushup(int p) { t[p].d = t[ls(p)].d * t[rs(p)].d; }
void modify(int p, int& q, int ps, int l = 1, int r = n) {
if (!q) q = newnode();
if (l == r) { t[q].d.f = t[p].d.f + 1;t[q].d.len = 1;return; }
if (ps <= mid) modify(ls(p), ls(q), ps, l, mid), rs(q) = rs(p);
else modify(rs(p), rs(q), ps, mid + 1, r), ls(q) = ls(p);
pushup(q);
assert(t[p].d.len == r - l + 1);
assert(t[q].d.len == r - l + 1);
}
void build(int& p, int l = 1, int r = n) {
p = newnode();
if (l == r) { t[p].d.len = 1;t[p].d.f = pll(0, 0);return; }
build(ls(p), l, mid); build(rs(p), mid + 1, r);
pushup(p);
assert(t[p].d.len == r - l + 1);
}
void print(int p, int l = 1, int r = n) {
if (l == r) {
assert(t[p].d.f.first == t[p].d.f.second);
for (int i = 0;i < t[p].d.f.first;++i) printf("%d ", P[l]);
return;
}
print(ls(p), l, mid); print(rs(p), mid + 1, r);
}
int cmp(int p, int q, int ps = n + 1, int l = 1, int r = n, bool fg = 0) {
if (q == 0) return -1;
if (l == r) {
ll v = t[p].d.f.fi + (ll)(ps == l) - t[q].d.f.fi;
if (v == 0) return 0;
return (v < 0) ? -1 : 1;
}
pll _p = t[ls(p)].d.f + ((l <= ps && ps <= mid) ? (pw[mid - ps]) : (pll{ 0,0 }));
pll _q = t[ls(q)].d.f;
if (_p == _q) return cmp(rs(p), rs(q), ps, mid + 1, r, fg);
return cmp(ls(p), ls(q), ps, l, mid, fg);
}
}
struct pp { int u, id; };
bool operator<(const pp a, const pp b) {
int t = segt::cmp(a.id, b.id);
return (t == 0) ? (a.id < b.id) : (t < 0);
}
bool operator>(const pp a, const pp b) { return b < a; }
pp dis[N];
bool vis[N]; int pre[N];
void dij() {
set<pp> Q;
segt::build(segt::root);
dis[1] = pp{ 1,0 };
segt::modify(segt::root, dis[1].id, w[1]);
Q.insert(dis[1]);
while (!Q.empty()) {
int u = Q.begin()->u;Q.erase(Q.begin());
if (vis[u]) continue;
vis[u] = 1;
if (u == n) break;
for (int i = head[u];i;i = nxt[i]) {
int v = pnt[i]; if (vis[v]) continue;
if (segt::cmp(dis[u].id, dis[v].id, w[v]) < 0) {
auto it = Q.find(dis[v]);
if (it != Q.end()) Q.erase(it);
dis[v].u = v;dis[v].id = 0;
segt::modify(dis[u].id, dis[v].id, w[v]);
Q.insert(dis[v]);
pre[v] = u;
}
}
}
}
int main() {
read(n, m); init(n);
for (int i = 1;i <= n;++i) read(P[i]), PP[P[i]] = i;
for (int i = 1;i <= n;++i) read(w[i]), w[i] = PP[w[i]];
for (int i = 1;i <= m;++i) {
int u, v;read(u, v);
adde(u, v);adde(v, u);
}
dij();
segt::print(dis[n].id);
puts("");
return 0;
}
#pragma GCC optimize(2)
#pragma GCC optimize(3)
#include <bits/stdc++.h>
#define fi first
#define se second
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<ll, ll> pll;
const int N = 1000010;
const int mod = 998244353;
const int p1 = 1e9 + 7;
const int p2 = 1e9 + 9;
const int base = 433;
template<size_t SIZE>
struct hashmap {
static const int MOD = (1 << 21);
int head[MOD], nxt[SIZE], st[SIZE], top, E;
ull key[SIZE];
inline int find(ull _key) {
int hah = _key & (MOD - 1);
for (int i = head[hah];i;i = nxt[i]) {
if (_key == key[i]) return i;
}
return -1;
}
inline int insert(ull _key) {
int hah = _key & (MOD - 1);
if (head[hah] == 0) st[++top] = hah;
E++;key[E] = _key;nxt[E] = head[hah];head[hah] = E;
return E;
}
inline void clear() {
while (top) head[st[top--]] = 0;E = 0;
}
};
hashmap<N * 2> vs, mp;
ll fpow(ll a, ll b) { ll r = 1;for (;b;b >>= 1, a = (a * a) % mod) r = (r * a) % mod;return r; }
ll inv[N], fac[N];ull pww[N << 1];
pll pw[N], hah[N];
char s[N];int n;
pll operator*(const pll a, const ll b) { return pll(a.fi * b % p1, a.se * b % p2); }
pll operator*(const pll a, const pll b) { return pll(a.fi * b.fi % p1, a.se * b.se % p2); }
pll operator+(const pll a, const ll b) { return pll((a.fi + b) % p1, (a.se + b) % p2); }
pll operator-(const pll a, const pll b) { return pll((a.fi - b.fi + p1) % p1, (a.se - b.se + p2) % p2); }
void print(pll a) { printf("(%lld,%lld)\n", a.fi, a.se); }
pll gethash(int l, int r) { return hah[r] - (hah[l - 1] * pw[r - l + 1]); }
void init() {
pw[0] = pll(1ll, 1ll);
for (int i = 1;i <= n;i++) {
pw[i] = pw[i - 1] * (ll)base;
hah[i] = hah[i - 1] * (ll)base + (ll)(s[i] - 'a' + 1);
}
fac[0] = fac[1] = inv[0] = inv[1] = 1;
for (int i = 2;i <= n;i++) {
fac[i] = fac[i - 1] * i % mod;
inv[i] = (mod - mod / i) * inv[mod % i] % mod;
}
pww[0] = { 1ull };
for (int i = 1;i <= 2 * n;i++) pww[i] = pww[i - 1] * 557ull;
}
ull tomask(pll a) {
ull x = (ull)a.fi << 32 | (ull)a.se;
x ^= x << 14;x ^= x >> 16;x ^= x << 7;
return x ^ 1919810;
}
int cnt[N << 1], id[N << 1];
int main() {
scanf("%s", s + 1);
n = strlen(s + 1);
init();
ll ress = 0;
for (int d = 1;d <= n;d++) {
int t = n / d, rs = n % d;
vs.clear();mp.clear();
ll ans = fac[t], res = 0;ull mask = 0;
for (int i = 1;i <= t;i++) {
// (i-1)*d+1 ~ i*d
ull tmp = tomask(gethash((i - 1) * d + 1, i * d));
int p = mp.find(tmp);
if (p == -1) {
cnt[p = mp.insert(tmp)] = 1;
}
else {
cnt[p]++;ans = (ans * inv[cnt[p]]) % mod;
}
id[i * 2 - 1] = p; mask += pww[p];
tmp = tomask(gethash((i - 1) * d + 1 + rs, i * d + rs));
p = mp.find(tmp);
if (p == -1) { p = mp.insert(tmp);cnt[p] = 0; }
id[i * 2] = p;
}
res = (res + ans) % mod;
vs.insert(mask);
if (rs) {
for (int i = t;i >= 1;i--) {
ans = (ans * cnt[id[i * 2 - 1]]) % mod;
cnt[id[i * 2 - 1]]--;
mask -= pww[id[i * 2 - 1]];
ans = (ans * inv[++cnt[id[i * 2]]]) % mod;
mask += pww[id[i * 2]];
if (vs.find(mask) != -1) continue;
vs.insert(mask);
res = (res + ans) % mod;
}
}
ress = (ress + res) % mod;
}
printf("%lld\n", ress);
return 0;
}
#include <bits/stdc++.h>
using namespace std;
#define LL long long
#define pii pair<int, int>
const int maxN = 1005, mod = 1472172389;
mt19937 rnd( time(NULL) );
int h[maxN + 1][26];
char ans[maxN + 1];
inline void update(int &x, int y) { x = (LL)x + y >= mod ? (LL)x + y - mod : (LL)x + y; }
struct Graph
{
int n, m, cnt;
int res[maxN + 1], tp[maxN + 1];
int f[maxN + 1][maxN + 1];
vector<pii> to[maxN + 1];
void init()
{
scanf("%d %d", &n, &m);
for(int i = 1; i <= m; i++)
{
int x, y;
char c[2];
scanf("%d %d %s", &x, &y, c);
to[x].push_back( pii(y, c[0] - 'a') );
}
for(int i = 1; i <= n; i++) f[0][i] = res[i] = 1;
}
int calc()
{
cnt ++;
int sum = 0;
for(int u = 1; u <= n; u++)
{
int res = 0;
for(int i = 0; i < to[u].size(); i++)
{
int v = to[u][i].first, c = to[u][i].second;
update(res, 1ll * h[cnt][c] * f[cnt - 1][v] % mod);
}
update(sum, f[cnt][u] = res);
}
return sum;
}
int get(int nc)
{
for(int i = 1; i <= n; i++) tp[i] = 0;
int sum = 0;
for(int u = 1; u <= n; u++)
for(int i = 0; i < to[u].size(); i++)
{
int v = to[u][i].first, c = to[u][i].second;
if(c != nc) continue;
int t = 1ll * res[u] * h[cnt][c] % mod;
update(tp[v], t);
update(sum, 1ll * t * f[cnt - 1][v] % mod);
}
return sum;
}
void upd()
{
for(int i = 1; i <= n; i++) res[i] = tp[i];
cnt --;
}
}G1, G2;
int main()
{
for(int i = 1; i <= 1001; i++)
for(int c = 0; c < 26; c++)
h[i][c] = rnd() % (mod - 1) + 1;
G1.init(); G2.init();
for(int i = 1; i <= 1001; i++)
if(G1.calc() != G2.calc())
{
for(int j = 1; j <= i; j++)
for(int c = 0; c < 26; c++)
if(G1.get(c) != G2.get(c))
{
ans[j] = c + 'a';
G1.upd(); G2.upd();
break;
}
printf("%s\n", ans + 1);
return 0;
}
puts("Same");
return 0;
}