您的位置:首页 > 理论基础 > 数据结构算法

HDU 4749 Parade Show 数据结构KMP变形

2016-07-23 12:20 316 查看
Parade Show

Every student has its own number, from 1 to n. (1<=n<=10^5), and they are standing from 1 to n in the increasing order the same with their number order. According to requirement of school authority, every queue is consisted of exactly m students. Because
students who stand adjacent in training are assigned consecutive number, for better arrangement, you will choose in students with in consecutive numbers. When you choose these m students, you will rearrange their numbers from 1 to m, in the same order with
their initial one.

  If we divide our students’ heights into k (1<=k<=25) level, experience says that there will exist an best viewing module, represented by an array a[]. a[i] (1<=i<=m)stands for the student’s height with number i. In fact, inside a queue, for every number pair
i, j (1<=i,j<=m), if the relative bigger or smaller or equal to relationship between the height of student number i and the height of student number j is the same with that between a[i] and a[j], then the queue is well designed. Given n students’ height array
x[] (1<=x[i]<=k), and the best viewing module array a[], how many well designed queues can we make at most?

 

Input

Multiple cases, end with EOF.

First line, 3 integers, n (1<=n<=10^5) m (1<=m<=n) k(1<=k<=25),

Second line, n students’ height array x[] (1<=x[i]<=k,1<=i<=n);

Third line, m integers, best viewing module array a[] (1<=a[i]<=k,1<=i<=m);

 

Output

One integer, the maximal amount of well designed queues.

 

Sample Input

10 5 10
2 4 2 4 2 4 2 4 2 4
1 2 1 2 1

 

Sample Output

1

解题思路:

输入的意思:n个学生,抽出连续的m个学生,他们的身高分为k个级别,然后就是n个身高,和最佳身高模式。

这题分析一下确实是kmp算法,但是有着很大的变形,首先因为是相对高度,不能直接的进行匹配,那怎么办呢

有一个思路:如果一个序列要和模式串匹配,那么对于每一个匹配的位置i他们前面的比他大的数字的数目比他小的数字的数目与他相等的数字的数目都要相等

(实际上如果比它小和相等的数字数目相等比它大也一定相等)满足这些条件就可以了,那么对应到kmp算法当中就是那个判断需要好好的修改一下

那么怎么判断?

1,kmp算法首先是通过自己和自己匹配找到的失配函数(失配函数就是next数组),这个匹配过程可以采用稍微暴力一点的做法

2,对于模式串,开一个数组g1[26][maxn],用来记录每一个位置他前面每一个数字有多少个。判断某一位置是否相等就可以用

这个g1数组

3,判断函数怎么写呢?(1)判断相等
4000
字符的数量是否相等(2)判断小于的字符数量是否相等,要写三个循环

4,仔细分析用同样的道理可以写出第二个匹配模式串的判断函数,

5,剩下的就是kmp的匹配了,每次匹配成功就记录一下,判断函数就是这一题的考点,写好之后基本就可以了

借鉴了网上的很多人的代码和思想,这题收获了很多,表示感谢。

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn = 100005 ;
int g1[26][maxn] ;
int g2[26][maxn] ;
int p[maxn] ;
int a[maxn] ;
int b[maxn] ;
int vis[maxn] ;
int n,m,t ;

bool judge2(int x,int y){
int c1 = 0;
int c2 = 0;
int c3 = 0;
if(g1[a[x]][x-1]!=g1[a[y]][y-1]-g1[a[y]][y-x])return false;
for(int i=1;i<a[x];i++)c1+=g1[i][x-1] ;
for(int i=1;i<a[y];i++)c2+=g1[i][y-1] ;
for(int i=1;i<a[y];i++)c3+=g1[i][y-x] ;
if(c1!=c2-c3)return false;
return true;
}
void getfail(){
p[1] = 0 ;
int j = 0 ;
for(int i=2;i<=n;i++){
while(j&&!judge2(j+1,i))j=p[j] ;
if(judge2(j+1,i))j++ ;
p[i] =j ;
}
return ;
}
bool judge(int x,int y){
int c1=0;
int c2=0;
int c3=0;
///判断相等
if(g1[a[x]][x-1]!=g2[b[y]][y-1]-g2[b[y]][y-x])return false;
///判断小于的
for(int i=1;i<a[x];i++)c1+=g1[i][x-1] ;
for(int i=1;i<b[y];i++)c2+=g2[i][y-1] ;
for(int i=1;i<b[y];i++)c3+=g2[i][y-x] ;
if(c1!=c2-c3)return false;
return true ;
}
void kmp(){
int j = 0 ;
for(int i=1;i<=m;i++){
while(j&&!judge(j+1,i))j=p[j] ;
if(judge(j+1,i))j++ ;
if(j==n){
vis[i] = 1 ;
//j = p[j] ;
j = 0 ;
}
}
}

int main(){
while(~scanf("%d%d%d",&m,&n,&t)){
memset(g1,0,sizeof(g1));
memset(g2,0,sizeof(g2));
memset(vis,0,sizeof(vis));
for(int i=1;i<=m;i++){
scanf("%d",&b[i]);
for(int j=1;j<=t;j++)g2[j][i] = g2[j][i-1];
g2[b[i]][i]++ ;
}
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
for(int j=1;j<=t;j++)g1[j][i] = g1[j][i-1] ;
g1[a[i]][i]++ ;
}
getfail() ;
//printf("yes\n");
kmp();
//printf("yes\n");
int ans = 0 ;
int i = 1;
while(i<=m){
if(vis[i]){
ans++ ;
i+=n ;
}else i++ ;
}
printf("%d\n",ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: