尋找字串A中完全包含字串B的最短子字串
阿新 • • 發佈:2019-01-09
已知兩個字串a和b。字串a的字元有可能重複,字串b中的字元不重複。
編寫一個演算法,尋找字串a的最短子字串,使得該子字串包含字串b中的所有字元。
這是一道典型的動態規劃題,有點類似程式設計之美中最短摘要生成那道題目。
可以使用兩個指標t_rear和t_front遍歷字串a。使用兩個指標rear和front記錄已發現的最短字串的邊界。
使用一個變數cnt記錄已經發現的b中的字元數。
定義一個數組tab[256]作為b中字元存在性的hash表,定義一個數組cal[256]存放已經發現的在ab中均出現的字元的個數。
1、剛開始t_rear和t_front均指向a的第一個字元。然後t_rear開始向後遍歷。
2、每當t_rear找到一個出現的在b中存在的字元,就讓cal中該字元計數加1。如果該字元第一次出現,則讓cnt也加1;
3、當cnt的數值等於b的字元個數時,t_front開始往後遍歷。當t_front發現一個在b中存在的字元時,就讓cal中的該字元計數減1。如果減1之後計數變為0,則記錄
此時t_rear和t_front的下標。如果t_rear-t_front<rear-front,則將rear和front更新為t_rear和t_front;
4、遍歷完a即可確定所求的最短子字串。
程式碼如下:
#include<iostream> using namespace std; void find(char a[], int Na, int tab[], int Nb); int main() { char a[]={'1', '4', '2', '3', '7', '3', '9', '3', '1', '0', '5', '7', '4', '6'}; char b[]={'3', '9', '1'}; int tab[256]={0}; for(int i=0; i<3; i++) { tab[b[i]]=1; } find(a, 14, tab, 3); system("pause"); } void find(char a[], int Na, int tab[], int Nb) { int front=0, rear=Na-1; int t_front=0, t_rear=0; int cnt=0; int cal[256]={0}; while(t_rear<Na) { if(tab[a[t_rear]]) { cout<<a[t_rear]<<endl; if(cal[a[t_rear]]==0) { cnt++; //cout<<cnt<<endl; } cal[a[t_rear]]++; if(cnt==Nb) { while(t_front!=t_rear) { if(tab[a[t_front]]) { cal[a[t_front]]--; if(cal[a[t_front]]==0) break; } t_front++; } if(t_rear-t_front < rear-front) { rear=t_rear; front=t_front; } t_front++; cnt--; } t_rear++; } else t_rear++; } for(int i=front; i<=rear; i++) { cout<<a[i]<<" "; } cout<<endl; }