1. 程式人生 > >2015年第六屆藍橋杯C/C++程式設計本科B組決賽 密文搜尋(程式設計大題)

2015年第六屆藍橋杯C/C++程式設計本科B組決賽 密文搜尋(程式設計大題)

2015年第六屆藍橋杯C/C++程式設計本科B組決賽題目彙總:


密文搜尋

福爾摩斯從X星收到一份資料,全部是小寫字母組成。
他的助手提供了另一份資料:許多長度為8的密碼列表。
福爾摩斯發現,這些密碼是被打亂後隱藏在先前那份資料中的。
請你編寫一個程式,從第一份資料中搜索可能隱藏密碼的位置。要考慮密碼的所有排列可能性。
資料格式:
輸入第一行:一個字串s,全部由小寫字母組成,長度小於1024*1024
緊接著一行是一個整數n,表示以下有n行密碼,1<=n<=1000
緊接著是n行字串,都是小寫字母組成,長度都為8
要求輸出:
一個整數, 表示每行密碼的所有排列在s中匹配次數的總和。

例如:
使用者輸入:
aaaabbbbaabbcccc
2
aaaabbbb
abcabccc
則程式應該輸出:
4
這是因為:第一個密碼匹配了3次,第二個密碼匹配了1次,一共4次。
資源約定:
峰值記憶體消耗 < 512M
CPU消耗  < 3000ms
請嚴格按要求輸出,不要畫蛇添足地列印類似:“請您輸入...” 的多餘內容。
所有程式碼放在同一個原始檔中,除錯通過後,拷貝提交該原始碼。
注意: main函式需要返回0
注意: 只使用ANSI C/ANSI C++ 標準,不要呼叫依賴於編譯環境或作業系統的特殊函式。
注意: 所有依賴的函式必須明確地在原始檔中 #include <xxx>, 不能通過工程設定而省略常用標頭檔案。

提交時,注意選擇所期望的編譯器型別。

思路:因為要求每行密碼的所有排列在s中匹配次數的總和,所以可以統計每行密碼中所包含的各個字母的個數,然後選取主串中的長度為8的區間,比較是否與密碼中包含的各個字母的個數相等。在選取主串中長度為8的區間時,實際上只有只有主串長度-7個長度為8的區間。

例如:  0  1   2   3  4   5   6  7  8  9  10        主串長度為11

則長度為8的區間只有0--7  1-- 8  2--9  3--10這4個,即11-4個。

#include <iostream>
#include <stdio.h>
#include <cstring>
using namespace std;

int main()
{
    int n;
    char str[1005],s[10];
    int  a[1005][26],b[26];

    memset(a,0,sizeof(a));

    scanf("%s", str);

    for(int i=0; i<=(strlen(str)-8); i++)
        for(int j=i; j<=i+7; j++)
            a[i][str[j]-'a']+=1;

    scanf("%d",&n);


    int sum=0;
    for(int k=0; k<n; k++)
    {
        int flag;
        memset(b,0,sizeof(b));

        scanf("%s", s);

        for(int i=0; i<strlen(s); i++)
            b[s[i]-'a']+=1;

        for(int i=0; i<=strlen(str)-8; i++)
        {
            flag=1;
            for(int j=0; j<26; j++)
            {
                if(a[i][j]!=b[j])
                {
                    flag=0;
                    break;
                }
            }
            if(flag==1)
                sum++;
        }
    }
    cout<<sum<<endl;
    return 0;
}