对每一个特征求前缀和,如果它减去前面的某一个地方的和,得到的每个特征是相等的,那么然后就可以更新答案。

  需要解决这个两个问题

  1.如何使答案尽量大?

    这个很简单,直接找尽量靠前的地方就好了。

  2,如何快速查找?

    考虑用后一项减去前一项得到的新的序列,

    然后就可以转换成找一个相等的序列,这个Hash就可以搞定。

Code

  1. #include<iostream>
  2. #include<fstream>
  3. #include<sstream>
  4. #include<cstdio>
  5. #include<cstring>
  6. #include<set>
  7. #ifndef WIN32
  8. #define Auto "%lld"
  9. #else
  10. #define Auto "%I64d"
  11. #endif
  12. using namespace std;
  13. typedef bool boolean;
  14. #define smin(a, b) (a) = min((a), (b))
  15. #define smax(a, b) (a) = max((a), (b))
  16.  
  17. typedef class Feature {
  18. public:
  19. int k;
  20. int lis[];
  21.  
  22. Feature() { }
  23. Feature(int x, int k):k(k) {
  24. for(int i = ; i < k; i++)
  25. if(x & ( << i))
  26. lis[i] = ;
  27. else
  28. lis[i] = ;
  29. }
  30.  
  31. friend boolean operator == (Feature& a, Feature& b) {
  32. for(int i = ; i < a.k; i++)
  33. if(a.lis[i] != b.lis[i])
  34. return false;
  35. return true;
  36. }
  37. }Feature;
  38.  
  39. template<typename Key, typename Val>
  40. class LinkedNode {
  41. public:
  42. Key key;
  43. Val val;
  44. int next;
  45. LinkedNode() { }
  46. LinkedNode(Key key, Val val, int next):key(key), val(val), next(next) { }
  47. };
  48.  
  49. template<typename Key, typename Val>
  50. class HashMap{
  51. protected:
  52. const static int moder = ;
  53. const static int C = ;
  54. int hashCode(Feature x) {
  55. int c = ;
  56. int hash = ;
  57. for(int i = ; i < x.k; i++) {
  58. hash = ((long long)hash + (x.lis[i] * 1LL * c) % moder + moder) % moder;
  59. c = (c * 1LL * C) % moder;
  60. }
  61. return hash;
  62. }
  63. public:
  64. int cn;
  65. int h[(moder + )];
  66. LinkedNode<Key, Val> *lis;
  67.  
  68. HashMap():cn() { }
  69. HashMap(int limit):cn() {
  70. lis = new LinkedNode<Key, Val>[(const int)(limit + )];
  71. memset(h, , sizeof(h));
  72. }
  73.  
  74. inline void insert(Key& k, Val v) {
  75. int hash = hashCode(k);
  76. lis[++cn] = LinkedNode<Key, Val>(k, v, h[hash]);
  77. h[hash] = cn;
  78. }
  79.  
  80. inline Val find(Key& k) {
  81. int hash = hashCode(k);
  82. for(int i = h[hash]; i; i = lis[i].next) {
  83. if(lis[i].key == k)
  84. return lis[i].val;
  85. }
  86. return -;
  87. }
  88. };
  89.  
  90. ifstream fin("feature.in");
  91. ofstream fout("feature.out");
  92.  
  93. int n, k;
  94. int *a;
  95.  
  96. inline void init() {
  97. fin >> n >> k;
  98. a = new int[(const int)(n + )];
  99. for(int i = ; i <= n; i++) {
  100. fin >> a[i];
  101. }
  102. }
  103.  
  104. int res = ;
  105. Feature org;
  106. Feature sumer;
  107. Feature cmp;
  108. HashMap<Feature, int> s;
  109. inline void solve() {
  110. s = HashMap<Feature, int>(n + );
  111. org = Feature(, k - );
  112. sumer = Feature(, k);
  113. cmp.k = k - ;
  114. s.insert(org, );
  115. for(int i = ; i <= n; i++) {
  116. for(int j = ; j < k; j++)
  117. if(a[i] & ( << j))
  118. sumer.lis[j]++;
  119. for(int j = ; j < k - ; j++)
  120. cmp.lis[j] = sumer.lis[j + ] - sumer.lis[j];
  121. int x = s.find(cmp);
  122. if(x == -)
  123. s.insert(cmp, i);
  124. else
  125. smax(res, i - x);
  126. }
  127. fout << res;
  128. }
  129.  
  130. int main() {
  131. init();
  132. solve();
  133. return ;
  134. }


  这个肯定是要Kmp,所以可以考虑Kmp。

  比起朴素的Kmp,多记录一些东西:

  fail[] 在文本串i位置匹配时对应模板串的位置j

  last[] 文本串实际有效的字符所构成的链表,这个记录文本串的位置i的前驱

  对于找到的一个串,沿着last往回找,找到的点打标记,然后把匹配到的位置的下一个last改成这个串的起点的前一个,把当前匹配到的位置改为起点前一个的fail值。

  最后找一遍标记处理一下就可以ac了。

  因为每个字符最多被访问两次(kmp + 打标记),所以总时间复杂度为O(2n + m),其中n为文本串的长度,m为模板串的长度。

Code

  1. #include<iostream>
  2. #include<fstream>
  3. #include<sstream>
  4. #include<cstdio>
  5. #include<cstring>
  6. #include<set>
  7. #ifndef WIN32
  8. #define Auto "%lld"
  9. #else
  10. #define Auto "%I64d"
  11. #endif
  12. using namespace std;
  13. typedef bool boolean;
  14. #define smin(a, b) (a) = min((a), (b))
  15. #define smax(a, b) (a) = max((a), (b))
  16.  
  17. int lenS, lenT;
  18. char T[];
  19. char S[];
  20. boolean enable[];
  21. char newS[];
  22.  
  23. inline void init() {
  24. scanf("%s", T);
  25. scanf("%s", S);
  26. lenS = strlen(S);
  27. lenT = strlen(T);
  28. }
  29.  
  30. int f[];
  31. inline void getFail() {
  32. int j = ;
  33. f[] = ;
  34. f[] = ;
  35. for(int i = ; i < lenT; i++) {
  36. j = f[i];
  37. while(j && T[i] != T[j]) j = f[j];
  38. f[i + ] = (T[i] == T[j]) ? (j + ) : ();
  39. }
  40. }
  41.  
  42. int fail[];
  43. int last[];
  44. inline void kmp() {
  45. getFail();
  46. int j = ;
  47. memset(enable, true, sizeof(boolean) * (lenS + ));
  48. for(int i = ; i < lenS; i++) last[i] = i - ;
  49. for(int i = ; i < lenS; i++) {
  50. while(j && S[i] != T[j]) j = f[j];
  51. if(S[i] == T[j]) j++;
  52. fail[i] = j;
  53. if(j == lenT) {
  54. int l = i;
  55. for(int cnt = ; cnt < lenT; cnt++)
  56. enable[l] = false, l = last[l];
  57. if(l == -) j = ;
  58. else j = fail[l];
  59. last[i + ] = l;
  60. }
  61. }
  62. }
  63.  
  64. inline void solve() {
  65. kmp();
  66. int top = ;
  67. for(int i = ; i < lenS; i++) {
  68. if(enable[i])
  69. newS[top++] = S[i];
  70. }
  71. newS[top] = ;
  72. puts(newS);
  73. }
  74.  
  75. int main() {
  76. freopen("sensitive.in", "r", stdin);
  77. freopen("sensitive.out", "w", stdout);
  78. init();
  79. solve();
  80. return ;
  81. }


  用AC自动机,然后差分数组去优化(虽然没快多少)

Code

  1. #include<iostream>
  2. #include<fstream>
  3. #include<sstream>
  4. #include<cstdio>
  5. #include<cstring>
  6. #include<set>
  7. #include<queue>
  8. #ifndef WIN32
  9. #define Auto "%lld"
  10. #else
  11. #define Auto "%I64d"
  12. #endif
  13. using namespace std;
  14. typedef bool boolean;
  15. #define smin(a, b) (a) = min((a), (b))
  16. #define smax(a, b) (a) = max((a), (b))
  17.  
  18. #define CharSet 26
  19.  
  20. typedef class TrieNode {
  21. public:
  22. int val;
  23. TrieNode* next[CharSet];
  24. TrieNode* last;
  25. TrieNode* fail;
  26. TrieNode():val(), last(NULL), fail(NULL) {
  27. memset(next, , sizeof(next));
  28. }
  29. }TrieNode;
  30.  
  31. int cti(char x) {
  32. if(x >= 'A' && x <= 'Z') return x - 'A';
  33. if(x >= 'a' && x <= 'z') return x - 'a';
  34. return -;
  35. }
  36.  
  37. typedef class Trie {
  38. public:
  39. TrieNode* root;
  40.  
  41. Trie() {
  42. root = new TrieNode();
  43. }
  44.  
  45. inline void insert(char* s) {
  46. int len = strlen(s);
  47. TrieNode* p = root;
  48. for(int i = ; i < len; i++) {
  49. int c = cti(s[i]);
  50. if(p->next[c] == NULL) {
  51. p->next[c] = new TrieNode();
  52. }
  53. p = p->next[c];
  54. }
  55. p->val = len;
  56. }
  57. }Trie;
  58.  
  59. typedef class AhoCorasick {
  60. public:
  61. Trie t;
  62.  
  63. inline void insert(char* s) {
  64. t.insert(s);
  65. }
  66.  
  67. inline void getFail() {
  68. queue<TrieNode*> que;
  69. t.root->fail = t.root;
  70. for(int i = ; i < CharSet; i++)
  71. if(t.root->next[i] != NULL) {
  72. t.root->next[i]->fail = t.root;
  73. que.push(t.root->next[i]);
  74. }
  75. while(!que.empty()) {
  76. TrieNode* e = que.front();
  77. que.pop();
  78. for(int i = ; i < CharSet; i++) {
  79. TrieNode* eu = e->next[i];
  80. if(eu == NULL) continue;
  81. TrieNode* f = e->fail;
  82. while(f != t.root && f->next[i] == NULL) f = f->fail;
  83. eu->fail = (f->next[i]) ? (f->next[i]) : (t.root);
  84. eu->last = (eu->fail->val) ? (eu->fail) : (eu->fail->last);
  85. que.push(eu);
  86. }
  87. }
  88. }
  89.  
  90. int findLast(TrieNode* p) {
  91. if(p) {
  92. int ret = findLast(p->last);
  93. return max(p->val, ret);
  94. }
  95. return ;
  96. }
  97.  
  98. inline void change(int* enable, int i, int len) {
  99. enable[i + ] += -;
  100. enable[i - len + ] += ;
  101. }
  102.  
  103. inline void find(char* s, int* enable) {
  104. int len = strlen(s);
  105. TrieNode* f = t.root;
  106. for(int i = ; i < len; i++) {
  107. int c = cti(s[i]);
  108. if(c == -) {
  109. f = t.root;
  110. continue;
  111. }
  112. while(f != t.root && f->next[c] == NULL) f = f->fail;
  113. if(f->next[c]) f = f->next[c];
  114. if(f->val) change(enable, i, f->val);
  115. else if(f->last) change(enable, i, findLast(f->last));
  116. }
  117. }
  118. }AhoCorasick;
  119.  
  120. int n;
  121. char s[];
  122. int enable[];
  123. AhoCorasick ac;
  124.  
  125. inline void init() {
  126. scanf("%d", &n);
  127. for(int i = ; i <= n; i++) {
  128. scanf("%s", s);
  129. ac.insert(s);
  130. }
  131. getchar();
  132. gets(s);
  133. }
  134.  
  135. inline void solve() {
  136. int len = strlen(s);
  137. memset(enable, , sizeof(boolean) * (len + ));
  138. ac.getFail();
  139. ac.find(s, enable);
  140. for(int i = ; i < len; i++) {
  141. if(i) enable[i] += enable[i - ];
  142. if(enable[i])
  143. s[i] = '*';
  144. }
  145. puts(s);
  146. }
  147.  
  148. int main() {
  149. freopen("cleanse.in", "r", stdin);
  150. freopen("cleanse.out", "w", stdout);
  151. init();
  152. solve();
  153. return ;
  154. }


  通过子串可以想到后缀自动机(虽然标程用的后缀数组,但是我不会QAQ)

  然后上面进行一个拓扑排序,记录根节点(空状态)到每个节点(状态)的总的方案数和经过边权为a的方案数。

  最后把所有的节点的方案数加起来就好了。

Code

  1. #include<iostream>
  2. #include<fstream>
  3. #include<sstream>
  4. #include<cstdio>
  5. #include<cstring>
  6. #include<set>
  7. #include<queue>
  8. #ifndef WIN32
  9. #define Auto "%lld"
  10. #else
  11. #define Auto "%I64d"
  12. #endif
  13. using namespace std;
  14. typedef bool boolean;
  15. #define smin(a, b) (a) = min((a), (b))
  16. #define smax(a, b) (a) = max((a), (b))
  17.  
  18. #define CharSet 26
  19.  
  20. int cti(char x) {
  21. return x - 'a';
  22. }
  23.  
  24. typedef class TrieNode {
  25. public:
  26. int len;
  27. int dag;
  28. long long cnt;
  29. long long cnta;
  30. TrieNode* next[CharSet];
  31. TrieNode* fail;
  32. TrieNode(int len = ):fail(NULL), len(len), cnt(), dag(), cnta() {
  33. memset(next, , sizeof(next));
  34. }
  35. }TrieNode;
  36.  
  37. typedef class SuffixAutomation {
  38. public:
  39. TrieNode* pool;
  40. TrieNode* top;
  41. TrieNode* root;
  42. TrieNode* last;
  43.  
  44. TrieNode* newnode(int len) {
  45. top->len = len;
  46. return top++;;
  47. }
  48.  
  49. SuffixAutomation() { }
  50. SuffixAutomation(int n) {
  51. pool = new TrieNode[( * n + )];
  52. top = pool;
  53. root = top++;
  54. last = root;
  55. }
  56.  
  57. inline void extends(char ch) {
  58. int c = cti(ch);
  59. TrieNode* node = newnode(last->len + );
  60. TrieNode* f = last;
  61. while(f && f->next[c] == NULL)
  62. f->next[c] = node, f = f->fail;
  63. if(!f) node->fail = root;
  64. else {
  65. TrieNode* p = f->next[c];
  66. if(p->len == f->len + )
  67. node->fail = p;
  68. else {
  69. TrieNode* q = newnode(f->len + );
  70. memcpy(q->next, p->next, sizeof(q->next));
  71. q->fail = p->fail;
  72. p->fail = q;
  73. node->fail = q;
  74. while(f && f->next[c] == p)
  75. f->next[c] = q, f = f->fail;
  76. }
  77. }
  78. last = last->next[c];
  79. }
  80. }SuffixAutomation;
  81.  
  82. int n;
  83. char S[];
  84. SuffixAutomation sam;
  85.  
  86. inline void init() {
  87. gets(S);
  88. n = strlen(S);
  89. sam = SuffixAutomation(n);
  90. }
  91.  
  92. void getDag() {
  93. for(TrieNode* p = sam.pool; p != sam.top; p++) {
  94. for(int i = ; i < CharSet; i++)
  95. if(p->next[i])
  96. p->next[i]->dag++;
  97. }
  98. }
  99.  
  100. queue<TrieNode*> que;
  101. void bfs() {
  102. sam.root->cnt = ;
  103. que.push(sam.root);
  104. while(!que.empty()) {
  105. TrieNode* e = que.front();
  106. que.pop();
  107. if(e->next[]) {
  108. e->next[]->dag--, e->next[]->cnta += e->cnt, e->next[]->cnt += e->cnt;
  109. if(!e->next[]->dag)
  110. que.push(e->next[]);
  111. }
  112. for(int i = ; i < CharSet; i++) {
  113. TrieNode* eu = e->next[i];
  114. if(eu) {
  115. eu->dag--;
  116. if(!eu->dag)
  117. que.push(eu);
  118. eu->cnt += e->cnt;
  119. eu->cnta += e->cnta;
  120. }
  121. }
  122. }
  123. }
  124.  
  125. long long res = ;
  126. inline void solve() {
  127. for(int i = ; i < n; i++)
  128. sam.extends(S[i]);
  129. getDag();
  130. bfs();
  131. for(TrieNode* p = sam.pool; p != sam.top; p++) {
  132. res += p->cnta;
  133. }
  134. printf(Auto, res);
  135. }
  136.  
  137. int main() {
  138. freopen("substring.in", "r", stdin);
  139. freopen("substring.out", "w", stdout);
  140. init();
  141. solve();
  142. return ;
  143. }

String & dp Problem Round 3 2017.4.22的更多相关文章

  1. 2017/11/22 Leetcode 日记

    2017/11/22 Leetcode 日记 136. Single Number Given an array of integers, every element appears twice ex ...

  2. 【CF954I】Yet Another String Matching Problem(FFT)

    [CF954I]Yet Another String Matching Problem(FFT) 题面 给定两个字符串\(S,T\) 求\(S\)所有长度为\(|T|\)的子串与\(T\)的距离 两个 ...

  3. Kickstart Round D 2017 problem A sightseeing 一道DP

    这是现场完整做出来的唯一一道题Orz..而且还调了很久的bug.还是太弱了. Problem When you travel, you like to spend time sightseeing i ...

  4. Educational Codeforces Round 16 E. Generate a String dp

    题目链接: http://codeforces.com/problemset/problem/710/E E. Generate a String time limit per test 2 seco ...

  5. Codeforces Round #282 Div.1 B Obsessive String --DP

    题意: 给两个串S,T,问能找出多少的S的(a1,b1)(a2,b2)..(ak,bk),使Sa1---Sb1,...Sak---Sbk都包含子串T,其中k>=1,且(a1,b1)...(ak, ...

  6. Educational Codeforces Round 40 I. Yet Another String Matching Problem

    http://codeforces.com/contest/954/problem/I 给你两个串s,p,求上一个串的长度为|p|的所有子串和p的差距是多少,两个串的差距就是每次把一个字符变成另一个字 ...

  7. codeforces 710E E. Generate a String(dp)

    题目链接: E. Generate a String time limit per test 2 seconds memory limit per test 512 megabytes input s ...

  8. hdu5362 Just A String(dp)

    转载请注明出处: http://www.cnblogs.com/fraud/          ——by fraud Just A String Time Limit: 2000/1000 MS (J ...

  9. Codeforces 954I Yet Another String Matching Problem(并查集 + FFT)

    题目链接  Educational Codeforces Round 40  Problem I 题意  定义两个长度相等的字符串之间的距离为:   把两个字符串中所有同一种字符变成另外一种,使得两个 ...

随机推荐

  1. centos 7 yum configuration; yum localinstall

    Linux下对于软件包的管理使用rpm管理方式.直接使用rpm包管理工具来进行rpm包的安装,升级,卸载时,对于最让人头疼的莫过与包之间的依赖关系.yum作为一个rpm包前端管理工具,可以自动处理依赖 ...

  2. version `GLIBC_2.14' not found问题

    先对比下源码编译.RPM 包和 YUM 三种安装方法的优劣: 源码编译:可以自行指定编译参数,自由度高,略显麻烦.但是如果不安装最新版本,BUGs 和 CVEs 是不会被修复的,和咸鱼没什么差别: R ...

  3. IDEA 配置环境和相关工具整理(新手入门)

    转载自:https://blog.csdn.net/moneyshi/article/details/79722360 因项目环境需要,开发工具需要统一 , 项目团队都使用idea,所以不得已自己也配 ...

  4. AWTK 全称为 Toolkit AnyWhere,是 ZLG 倾心打造的一套基于 C 语言开发的 GUI 框架(三平台+2个手机平台+嵌入式)

    最终目标: 支持开发嵌入式软件. 支持开发Linux应用程序. 支持开发MacOS应用程序. 支持开发Windows应用程序. 支持开发Android应用程序. 支持开发iOS应用程序. 支持开发2D ...

  5. 优云软件助阵ArchSummit全球架构师峰会

    由极客邦科技与 InfoQ 中国主办的 ArchSummit 全球架构师峰会深圳站,于 7 月 7 日 - 8 日在深圳华侨城洲际酒店举办. 本次大会特邀 100 多位国内外技术专家,与1000余名技 ...

  6. webview与js交互(转)

    原文:http://www.cnblogs.com/vanezkw/archive/2012/07/02/2572799.html 对于android初学者应该都了解webView这个组件.之前我也是 ...

  7. java进程和线程的区别

    什么是进程,什么是线程系统要做一件事,运行一个任务,所有运行的任务通常就是一个程序:每个运行中的程序就是一个进程,这一点在任务管理器上面可以形象的看到.当一个程序运行时,内部可能会包含多个顺序执行流, ...

  8. (3.10)mysql基础深入——mysqld 服务器与客户端连接过程 源码分析【待写】

    (3.10)mysql基础深入——mysqld 服务器与客户端连接过程 源码分析[待写]

  9. Spark Shuffle Write阶段磁盘文件分析

    这篇文章会详细介绍,Sort Based Shuffle Write 阶段是如何进行落磁盘的 流程分析 入口处: org.apache.spark.scheduler.ShuffleMapTask.r ...

  10. PHP操作Redis常用技巧

    这篇文章主要介绍了PHP操作Redis常用技巧,结合实例形式总结分析了php针对redis的连接.认证.string.hash等操作技巧与注意事项,需要的朋友可以参考下 本文实例讲述了PHP操作Red ...