Chinaunix首页 | 论坛 | 博客
  • 博客访问: 17786
  • 博文数量: 11
  • 博客积分: 267
  • 博客等级: 二等列兵
  • 技术积分: 135
  • 用 户 组: 普通用户
  • 注册时间: 2011-10-20 21:56
文章分类

全部博文(11)

文章存档

2011年(11)

我的朋友

分类: C/C++

2011-10-27 15:28:22

就是一个kmp的变形,关键是怎么计算next数组,对于该题就是:找出最长的前缀序列,使得该序列的偏序关系
(也有acmer称为串排名)与相应的后缀序列的偏序关系相同。顺着这个思路,你可能会想怎样快速比较两个序
列的偏序关系。我想了好久,没有头绪。。。 注意到1<=S<=25这个条件,也就是说序列中的元素是有限制的,这样我们可以通过统计序列中元素出现到次数来比较偏序关系。这时有一个结论要用到:

两个序列的偏序关系相同当且仅当这两个序列的每个位置上的元素前面等于它的元素个数和小于它的元素个数都相等

  1. #include <stdio.h>
  2. #include <string.h>

  3. #define MAX_COW_NUMBER 100001
  4. #define MAX_PTN_NUMBER 25001

  5. int N, K, S;
  6. int cowline[MAX_COW_NUMBER];
  7. int pattern[MAX_PTN_NUMBER];
  8. int next[MAX_PTN_NUMBER];

  9. int res[MAX_COW_NUMBER];
  10. int resNum;

  11. // p[i][j] indicates the number of j in the front i numbers
  12. int array1[MAX_PTN_NUMBER][26];
  13. int array2[MAX_COW_NUMBER][26];

  14. void preprocess() {
  15.     int i, j;
  16.     for( i=1; i<=S; i++ ) {
  17.     array1[0][i] = array2[0][i] = 0;
  18.     }
  19.     for( i=1; i<=K; i++ ) {
  20.     for( j=1; j<=S; j++ ) {
  21.      array1[i][j] = array1[i-1][j] + (j==pattern[i]);
  22.     }
  23.     }
  24.     for( i=1; i<=N; i++ ) {
  25.     for( j=1; j<=S; j++ ) {
  26.      array2[i][j] = array2[i-1][j] + (j==cowline[i]);
  27.     }
  28.     }
  29. }

  30. int isMatch(int* p, int (*ary1)[26], int pk, int ps, int* t, int (*ary2)[26], int tk, int ts) {
  31.     int i;
  32.     // compute the number of numbers which are less than p[pk]
  33.     int pLessNumber = 0, tLessNumber = 0, pEqualNumber = 0, tEqualNumber = 0;
  34.     for( i=1; i<p[pk]; i++ )
  35.     pLessNumber += ary1[pk-1][i] - ary1[pk-ps-1][i];
  36.     for( i=1; i<t[tk]; i++ )
  37.     tLessNumber += ary2[tk-1][i] - ary2[tk-ts-1][i];
  38.     pEqualNumber = ary1[pk-1][p[pk]] - ary1[pk-ps-1][p[pk]];
  39.     tEqualNumber = ary2[tk-1][t[tk]] - ary2[tk-ts-1][t[tk]];

  40.     return pLessNumber == tLessNumber && pEqualNumber == tEqualNumber;
  41. }

  42. void compute_prefix_function() {
  43.     int i;
  44.     int k;
  45.     next[1] = 0;
  46.     next[2] = 1;
  47.     k = 1;
  48.     for( i=3; i<=K; i++ ) {
  49.     int match = isMatch(pattern, array1, k+1, k, pattern, array1, i, k);
  50.     while( k>0 && !match) { // compare pattern[k+1] with pattern[i]
  51.      k = next[k];
  52.      match = isMatch(pattern, array1, k+1, k, pattern, array1, i, k);
  53.     }
  54.     if( match )
  55.      k++;
  56.     next[i] = k;
  57.     }
  58. }

  59. void Knuth_Morris_Pratt() {
  60.     int i;
  61.     int k = 0;
  62.     for( i=1; i<=N; i++ ) {
  63.     int match = isMatch( pattern, array1, k+1, k, cowline, array2, i, k);
  64.     while( k>0 && !match) {
  65.      k = next[k];
  66.      match = isMatch( pattern, array1, k+1, k, cowline, array2, i, k);
  67.     }
  68.     if( match ) {

  69.      k++;
  70.     }


  71.     if( k == K ) {
  72. //     printf("%d", i-K+1);
  73.      res[resNum++] = i-K+1;
  74.      k = next[k];    
  75.     }
  76.     }
  77.     printf("%d\n", resNum);
  78.     for( i=0; i<resNum; i++)
  79.     printf("%d\n", res[i]);

  80. }

  81. int main() {
  82.     int i;
  83.     while( EOF != scanf("%d %d %d", &N, &K, &S) ) {
  84.     for( i=1; i<=N; i++)
  85.      scanf("%d", &cowline[i]);
  86.     for( i=1; i<=K; i++ )
  87.      scanf("%d", &pattern[i]);

  88.     preprocess();
  89.     compute_prefix_function();
  90.     resNum = 0;
  91.     Knuth_Morris_Pratt();
  92.     }
  93.     
  94.     return 0;
  95. }

阅读(1749) | 评论(0) | 转发(0) |
0

上一篇:没有了

下一篇:学习Linux的三大网站

给主人留下些什么吧!~~