1. 程式人生 > 其它 >【藍橋vip試題】ALGO-24 演算法訓練 統計單詞個數

【藍橋vip試題】ALGO-24 演算法訓練 統計單詞個數

問題描述:

  給出一個長度不超過200的由小寫英文字母組成的字母串(約定;該字串以每行20個字母的方式輸入,且保證每行一定為20個)。要求將此字母串分成k份 (1<k<=40),且每份中包含的單詞個數加起來總數最大(每份中包含的單詞可以部分重疊。當選用一個單詞之後,其第一個字母不能再用。例 如字串this中可包含this和is,選用this之後就不能包含t)。單詞在給出的一個不超過6個單詞的字典中。
  要求輸出最大的個數。

輸入格式

  第一行有二個正整數(p,k)
  p表示字串的行數;
  k表示分為k個部分。
  接下來的p行,每行均有20個字元。
  再接下來有一個正整數s,表示字典中單詞個數。(1<=s<=6)


  接下來的s行,每行均有一個單詞。

輸出格式   每行一個整數,分別對應每組測試資料的相應結果。 樣例輸入 樣例輸入
1 3
thisisabookyouareaoh
4
is
a
ok
sab

樣例輸出

7 
樣例輸出 資料規模和約定   長度不超過200,1<k<=40,字典中的單詞數不超過6。

-----------分界線-----------

這道題算是很基礎的字串模擬題,資料規模只有200,暴力模擬就完事

#對於入門選手,講一下字串的比較

  兩個字串相等,就代表了他們對應下標的元素相同。我們需要知道字串的長度,然後用迴圈來依次比較。

#include<bits/stdc++.h>
using
namespace std; int main() { int len_a,len_b,flag; char a[10],b[10]; gets(a); gets(b); len_a=strlen(a); len_b=strlen(b); if(len_a!=len_b)//如果長度不一樣,那一定不同 printf("No\n"); else { flag=1;//flag是標記 //這裡用len_a或者len_b都可以,因為len_a==len_b for(int i=0;i<len_a;i++) {
if(a[i]!=b[i])//如果a和b的對應位置元素出現不同的 { flag=0;//標記變成0,即為不同 break;/跳出迴圈,後面的就不用比了 } } if(flag==1) printf("Yes\n"); else printf("No\n"); } return 0; }
字串比較

然後分開講一下程式碼思路:

1、輸入

  題目給的輸入比較有意思,是每行20個字元,輸入p行。對於字串的讀入可以直接用getchar(),要記得讀掉換行符,不然會出錯。然後,二維陣列不方便換行,所以用了將原來的ch[i][j]換成了ch[i*20+j],這樣轉換下標就可以把輸入資料轉換為一維。

輸入部分程式碼:

cin>>p>>k;
for(int i=0;i<p;i++)
{
    getchar();//換行符!!!
    for(int j=0;j<20;j++)
        ch[i*20+j]=getchar();//正常資料讀入 
}
cin>>s;
for(int i=0;i<s;i++)
{
    cin>>d[i];//讀入字典
    len[i]=strlen(d[i]);//len陣列記錄字典長度
}

2、判斷
   判斷部分,遍歷每一個元素。假設他們都是頭,依次進行判斷,如果當前字元與字典中的某一串的頭相同,則繼續進行後續的判斷(我用了自定義的check函式)。如果當前的ch[i]可以作為一個頭來滿足一個單詞,則ans++,同時更新end。end是當前滿足的單詞的最後一個下標,更新他的條件在程式碼中。當出現同一個頭不同詞的時候,如果不滿足更新end條件,是不會增加ans的。

bool check(int i,int j)
{
    for(int v=1;v<len[j];v++)
    {
        if(ch[i+v]!=d[j][v])
            return 0;
    }
    return 1;
}
Check
for(int i=0;i<p*20;i++)
{
    for(int j=0;j<s;j++) 
    {
        flag=0;
        if(ch[i]==d[j][0])
        {
            if( check(i,j) )
            {
                if(end<i+len[j])
                    end=i+len[j];
                ans++;
                flag=1;
                break;
            }
        }
        if( !flag && k>1 && i>end)
            k--;
    }
}

3、後續處理及輸出

 經過思考,當無效元素足夠多的時候,可以隨便切並且對答案沒有影響。但是會出現一些不夠切的情況

比如:

給定字串為abcabc,字典僅有abc,需要分成k=3段

我們可以看到,如果不考慮分段的話,(abc)(abc)即為最優解,ans=2。但是這樣只分了兩段,為了滿足3段的條件,我們只能去浪費一個單詞來滿足分段。隨便分一下變成了 (abc)(ab)(c),這時滿足了k=3的需求,