生物学家正在对n个物种进行研究。

其中第i个物种的DNA序列为s[i],其中的第j个碱基为s[i][j],碱基一定是A、T、G、C之一。

生物学家想找到这些生物中一部分生物的一些共性,他们现在关注那些至少在m个生物中出现的长度为k的连续碱基序列。

准确的说,科学家关心的序列用2m元组(i1,p1,i2,p2....im,pm)表示,

满足: 1<=i1<i2<....<im<=n;

且对于所有q(0<=q<k), s[i1][p1+q]=s[i2][p2+q]=....=s[im][pm+q]。

现在给定所有生物的DNA序列,请告诉科学家有多少的2m元组是需要关注的。

如果两个2m元组有任何一个位置不同,则认为是不同的元组。

【输入格式】

输入的第一行包含三个整数n、m、k,两个整数之间用一个空格分隔,意义如题目所述。

接下来n行,每行一个字符串表示一种生物的DNA序列。

DNA序列从1至n编号,每个序列中的碱基从1开始依次编号,不同的生物的DNA序列长度可能不同。

【输出格式】

输出一个整数,表示关注的元组个数。

答案可能很大,你需要输出答案除以1000000007的余数。

【样例输入】

3 2 2
ATC
TCG
ACG

【样例输出】

2

再例如:

【样例输入】

4 3 3
AAA
AAAA
AAA
AAA

【样例输出】

7

【数据规模与约定】

对于20%的数据,k<=5,所有字符串总长L满足L <=100

对于30%的数据,L<=10000

对于60%的数据,L<=30000

对于100%的数据,n<=5,m<=5,1<=k<=L<=100000

保证所有DNA序列不为空且只会包含’A’ ’G’ ’C’ ’T’四种字母

资源约定:

峰值内存消耗 < 256M

CPU消耗 < 1000ms

请严格按要求输出,不要画蛇添足地打印类似:“请您输入...” 的多余内容。

所有代码放在同一个源文件中,调试通过后,拷贝提交该源码。

注意: main函数需要返回0

注意: 只使用ANSI C/ANSI C++ 标准,不要调用依赖于编译环境或操作系统的特殊函数。

注意: 所有依赖的函数必须明确地在源文件中 #include , 不能通过工程设置而省略常用头文件。

提交时,注意选择所期望的编译器类型。

 

代码:

#include <iostream>
#include <algorithm>
#include <cmath>
#include <map>
#include <vector>
#define mod 1000000007
using namespace std;

int n,m,k,c;
string s;
map<string,int> mp[5];
map<string,int> has;
void dfs(vector<int> &ans,int kk,int sum,int num) {
    if(num >= m) {
        c = (c + sum) % mod;
        return;
    }
    for(int i = kk;i < ans.size();i ++) {
        dfs(ans,i + 1,sum * ans[i] % mod,num + 1);
    }
}
int main() {
    cin>>n>>m>>k;
    for(int i = 0;i < n;i ++) {
        cin>>s;
        for(int j = 0;j + k <= s.size();j ++) {
            string t = s.substr(j,k);
            if(!mp[i][t]) has[t] ++;
            mp[i][t] ++;
        }
    }
    for(map<string,int>::iterator it = has.begin();it != has.end();it ++) {
        if(it -> second < m) continue;
        vector<int> ans;
        for(int i = 0;i < n;i ++) {
            if(mp[i][it -> first]) ans.push_back(mp[i][it -> first]);
        }
        dfs(ans,0,1,0);
    }
    cout<<c;
}