#include<cstdio> #include<cstring> #include<cmath> #include<algorithm> #include<queue> using namespace std; typedef long long ll; /* const int size = 26;//字典树节点大小 const int base = 'a';//字典树 const int maxn = 100005;//字典树大小(便于各种操作) class tire { public: tire *next[size], *fail; int cnt, id; //各种节点设置 tire(){ cnt = 0; fail = NULL; memset(next, 0, sizeof(next)); }; };//字典树节点设置 class Ac_machine { private: tire *root;//根节点建立 tire *node[maxn];//与id相对立,便于各种操作 int tot;//字典树大小 char s[maxn];//读入字符串 char S[maxn];//母串 public: Ac_machine(){} void clear(){ node[0] = root = new tire; tot = 0; }//初始化 void insert(int);//插入多个字符串 int insert();//插入字符串,返回字符串大小 void getfail(); //获取失配指针 int getmother();//获得匹配的母串,返回母串大小 int work_out();//求解函数,依照题目不同而不同,返回答案 };//ac自动机设置 int Ac_machine::getmother(){ scanf("%s", S); return strlen(S); } void Ac_machine::insert(int n){ while (n--) insert(); } int Ac_machine::insert() { scanf("%s", s); tire *now = root; for (int i = 0, k; s[i]; i++) { k = s[i] - base; if (!now->next[k]) { node[++tot] = now->next[k] = new tire; now->next[k]->id = tot; } now = now->next[k]; } now->cnt++; //可以插入一些字典树的设置 return strlen(s); } void Ac_machine::getfail() { queue<tire*> p; root->fail = root; for (int i = 0; i < size; i++) if (root->next[i]) { root->next[i]->fail = root; p.push(root->next[i]); } else root->next[i] = root; tire *now; while (!p.empty()) { now = p.front(); p.pop(); now->cnt += now->fail->cnt; //可以插入统计子串个数等操作 for (int i = 0; i < size; i++) if (now->next[i]) { now->next[i]->fail = now->fail->next[i]; p.push(now->next[i]); } else now->next[i] = now->fail->next[i]; } } int Ac_machine::work_out() { int ans = 0; getmother(); getfail(); tire *now = root; //for (int i = 0; i < maxn; i++) printf("%d\n", node[i]->cnt); for (int i = 0, k; S[i]; i++) { k = S[i] - base; now = now->next[k]; ans += now->cnt; } return ans;//返回子串出现次数 } AC自动机 */ /* void getnext(char *s) { nt[0] = -1; for (int i = 0, j; s[i]; i++) { j = nt[i]; while (j >= 0 && s[i] != s[j]) j = nt[j]; nt[i + 1] = j + 1; } } KMP算法 */ /* int cmp(int x, char a, char b) { if (a > b) return x - 0; if (a < b) return 1 - x; return 2; } int present(int z,char *s) { int i, j, k, x, y; for (i = 0, j = 1, k = 0; k < n;) { if (i == j) { j++; k = 0; } x = (i + k) % n; y = (j + k) % n; switch (cmp(z, s[x], s[y])) { case 0:i += k + 1; k = 0; break; case 1:j += k + 1; k = 0; break; case 2:k++; break; } } return min(i, j); } 最大最小表示法 present(0)代表最小 */ /* long long mod(long long a,long long b) { return (a % b + b) % b; } long long inv(long long x,long long b) { long long tot = 1, i = b - 2, ans = x; while (i) { if (i & 1) tot = mod(tot * ans,b); ans = mod(ans * ans,b); i >>= 1; } return mod(tot,b); } 欧拉定理求逆元 long long inv(long long x, long long m) { if (x == 1) return x; return inv(m % x, m)*(m - m / x) % m; } x < m的逆元 void egcd(long long a, long long b, long long &x, long long &y) { if (b == 0){ x = 1, y = 0; return; } egcd(b, a % b, x, y); long long t = x; x = y, y = t - a / b * y; } 扩展欧几里得求逆元 求解逆元 */ /* const int base=1000000007; const int size = 4; struct Matrix { int m[size][size]; Matrix() { memset(m, 0, sizeof(m)); } void operator =(const Matrix&b) { memcpy(m, b.m, sizeof(m)); } Matrix operator *(const Matrix&b) { Matrix c; for (int i = 0; i < size;i++) for (int j = 0; j < size;j++) for (int k = 0; k < size; k++) c.m[i][k] = (c.m[i][k] + m[i][j] * b.m[j][k]) % base; return c; } Matrix get(int x) { Matrix a, b = *this; for (int i = 1, f = 0; x; x >>= 1) { if (x & 1) if (f) a = a * b; else a = b, f = 1; b = b * b; } return b; } }; 矩阵乘法 */ /* const int maxn=100005; const int low(int x) { return x&-x; } int f[maxn]; void add(int x,int y) { for (int i=x;i<maxn;i+=low(i)) f[x]+=y; } int get(int x) { int sum=0; for (int i=x;i;i-=low(i)) sum+=f[x]; return sum; } 树状数组 */ /* const int maxn=100005; int f[maxn],N,n; void add(int x, int y) { x = x + N; a[x] += y; for (x >>= 1; x; x >>= 1) a[x] = a[x + x] + a[x + x + 1]; } int find(int l, int r) { int tot = 0; for (l += N - 1, r += N + 1; l ^ r ^ 1; l >>= 1, r >>= 1) { if (~l & 1) tot += a[l ^ 1]; if (r & 1) tot += a[r ^ 1]; } return tot; } zkw线段树 */ /* struct bignum { int len, s[maxn]; bignum() { memset(s, 0, sizeof(s)); len = 1; } bignum operator = (const bignum &b) { len = b.len; memcpy(s, b.s, maxn*sizeof(int)); return *this; } }; bignum operator +(const bignum &a, const bignum &b) { bignum c; int jw = 0, i; for (i = 0; i < max(b.len, a.len) || jw>0; i++) { if (i < a.len) jw += a.s[i]; if (i < b.len) jw += b.s[i]; c.s[i] = jw % base; jw /= base; } c.len = i; return c; } 高精度加法 */ /* const int maxn = 100005; class suffix { private: char s[maxn]; int r[maxn], rr[maxn], w[maxn], h[maxn]; int sa[maxn], rk[maxn], n, m, rmq[maxn][20]; public: bool get(){ if (scanf("%s", s + 1) != 1) return false; n = strlen(s + 1); m = 256; return true; } void pre() { int *x = r, *y = rr, i, j, p; for (i = 1; i <= m; i++) w[i] = 0; for (i = 1; i <= n; i++) w[x[i] = s[i]]++; for (i = 1; i <= m; i++) w[i] += w[i - 1]; for (i = n; i; i--) sa[w[s[i]]--] = i; for (j = 1, p = 1; p < n; j += j, m = p) { for (p = 1, i = n - j + 1; i <= n; i++) y[p++] = i; for (i = 1; i <= n; i++) if (sa[i] > j) y[p++] = sa[i] - j; for (i = 0; i <= m; i++) w[i] = 0; for (i = 1; i <= n; i++) w[x[y[i]]]++; for (i = 1; i <= m; i++) w[i] += w[i - 1]; for (i = n; i; i--) sa[w[x[y[i]]]--] = y[i]; for (swap(x, y), p = 1, x[sa[1]] = 1, i = 2; i <= n; i++) x[sa[i]] = (y[sa[i]] == y[sa[i - 1]] && y[sa[i] + j] == y[sa[i - 1] + j]) ? p : ++p; } for (int i = 1; i <= n; i++) rk[sa[i]] = i; for (int i = 1, k = 0, j; i <= n; h[rk[i++]] = k) for (k ? k-- : 0, j = sa[rk[i] - 1]; s[i + k] == s[j + k]; k++); } void getrmq() { for (int i = 1; i <= n; i++) rmq[i][0] = h[i]; for (int j = 1; (1 << j) <= n; j++) for (int i = 1; i + (1 << j) - 1 <= n; i++) rmq[i][j] = min(rmq[i][j - 1], rmq[i + (1 << j - 1)][j - 1]); } void work() { int ans = 0; for (int i = 1; i <= n; i++) ans += n - sa[i] + 1 - h[i]; printf("%d\n", ans); } }; 后缀数组 */ /* struct DLX { #define maxn 500005 #define F(i,A,s) for (int i=A[s];i!=s;i=A[i]) int L[maxn], R[maxn], U[maxn], D[maxn]; int row[maxn], col[maxn], ans[maxn], cnt[maxn]; int m, num, sz; void add(int now, int l, int r, int u, int d, int x, int y) { L[now] = l; R[now] = r; U[now] = u; D[now] = d; row[now] = x; col[now] = y; } void reset(int m)//约束列的大小 { num = 0x7FFFFFFF; this->m = m; for (int i = 0; i <= m; i++) { add(i, i - 1, i + 1, i, i, 0, i); cnt[i] = 0; } L[0] = m; R[m] = 0; sz = m + 1; } void insert(int x, int y)//按顺序插入节点 { int ft = sz - 1; if (row[ft] != x) { add(sz, sz, sz, U[y], y, x, y); U[D[sz]] = sz; D[U[sz]] = sz; } else { add(sz, ft, R[ft], U[y], y, x, y); R[L[sz]] = sz; L[R[sz]] = sz; U[D[sz]] = sz; D[U[sz]] = sz; } ++cnt[y]; ++sz; } //精确覆盖 void remove(int now) { R[L[now]] = R[now]; L[R[now]] = L[now]; F(i, D, now) F(j, R, i) { D[U[j]] = D[j]; U[D[j]] = U[j]; --cnt[col[j]]; } } void resume(int now) { F(i, U, now) F(j, L, i) { D[U[j]] = j; U[D[j]] = j; ++cnt[col[j]]; } R[L[now]] = now; L[R[now]] = now; } bool dfs(int x) { //if (x + A() >= num) return; if (!R[0]) { num = min(num, x); return true; } int now = R[0]; F(i, R, 0) if (cnt[now]>cnt[i]) now = i; remove(now); F(i, D, now) { ans[x] = row[i]; F(j, R, i) remove(col[j]); if (dfs(x + 1)) return true; F(j, L, i) resume(col[j]); } resume(now); return false; } //精确覆盖 //重复覆盖 void Remove(int now) { F(i, D, now) { L[R[i]] = L[i]; R[L[i]] = R[i]; } } void Resume(int now) { F(i, U, now) L[R[i]] = R[L[i]] = i; } int vis[maxn]; int flag[maxn]; int A() { int dis = 0; F(i, R, 0) vis[i] = 0; //F(i, R, 0) dis++; //求解最大值 F(i, R, 0) if (!vis[i]) { dis++; vis[i] = 1; F(j, D, i) F(k, R, j) vis[col[k]] = 1; } return dis; } void Dfs(int x) { if (!R[0]) num = x; else if (x + A()<num) { int now = R[0]; F(i, R, 0) if (cnt[now]>cnt[i]) now = i; F(i, D, now) //可以添加约束条件 { Remove(i); F(j, R, i) Remove(j); Dfs(x + 1); F(j, L, i) Resume(j); Resume(i); } } } //重复覆盖 }dlx; dlx模板*/ int main() { return 0; }