【解题报告】[动态规划] - PID90 / 未出现的子串
原题地址:http://www.rqnoj.cn/problem/90
解题思路:题目看起来不太像动态规划。。。
我用一个数组f[i][j]来表示在数组第i个元素的后面第一次出现j的位置,为-1则是没出现过。
然后每次查找最大的位置即可。如题目例子中:
f 1 3 5 2 4 1 3 5 2 2 2 2 3 4 1 5 3 2
-----------------------------------------------------------
1 1 6 6 6 6 6 15 15 15 15 15 15 15 15 15 -1 -1 -1 -1
2 4 4 4 4 9 9 9 9 9 10 11 12 18 18 18 18 18 18 -1
3 2 2 7 7 7 7 7 13 13 13 13 13 13 17 17 17 17 -1 -1
4 5 5 5 5 5 14 14 14 14 14 14 14 14 14 -1 -1 -1 -1 -1
5 3 3 3 8 8 8 8 8 16 16 16 16 16 16 16 16 -1 -1 -1
从第0位置开始查找,找出f[0][1]~f[0][q]中的最大值。下一次就从这个最大值的地方开始查找,直到查找到f[0][1]~f[0][q]存在-1为止。
查找的次数就是答案。
代码:
1 #include<iostream> 2 #include<stdio.h> 3 using namespace std; 4 int s[100005]; 5 int f[100005][10]; 6 int n,q; 7 int main() 8 { 9 int i,j; 10 //freopen("out.txt","w",stdout); 11 scanf("%d%d",&n,&q); 12 for(i=1;i<=n;i++) 13 { 14 scanf("%d",&s[i]); 15 } 16 int fend[10]; 17 for(j=1;j<=q;j++) 18 { 19 fend[j]=-1; 20 } 21 for(i=n;i>=0;i--) 22 { 23 for(j=1;j<=q;j++) 24 { 25 f[i][j]=fend[j]; 26 } 27 fend[s[i]]=i; 28 }/* 29 for(j=1;j<=q;j++) 30 { 31 for(i=0;i<=n;i++) 32 { 33 printf("%3d",f[i][j]); 34 } 35 printf("\n"); 36 }*/ 37 int ans=1; 38 i=0; 39 int max; 40 while(1) 41 { 42 max=0; 43 for(j=1;j<=q;j++) 44 { 45 if(f[i][j]==-1) {max=-1;break;} 46 if(max<f[i][j]) max=f[i][j]; 47 } 48 if(max==-1) break; 49 else 50 { 51 i=max; 52 ans++; 53 //printf("i=%d\n",i); 54 } 55 } 56 printf("%d\n",ans); 57 return 0; 58 }