好气啊~在dfs到>r的时候忘记return了,调了好久
暴力枚举字符串,记录最长的以当前结尾的后缀等于该字符串的前缀的长度k。若新加的字符c小于a[k]则不合法,若等于a[k]则k++,否则k=0。爆搜剪枝即可。
可以证明,最多枚举$ n*m^n $就能出结果
#include <iostream>
#include <cstdio>
#define INF (1<<30)
#define N 35
using namespace std;
int a[N],p[N],n,m,L,R;
inline void out(int len) {
for (int i=1;i<=len;i++) {
char c = a[i] + 'a' - 1;
putchar(c);
}
putchar('\n');
}
int dfs(int dep,int rk,int kmp) { //返回扩展了多少新串
int r = kmp == 0;
if (rk+r > R) return 0;
if (r && L<=rk+r && rk+r<=R) out(dep-1);
if (dep > n) return r;
for (int i=1;i<=m;i++) {
a[dep] = i;
if (a[dep] == a[kmp+1]) {
int tmp = dfs(dep+1,rk+r,kmp+1);
r += tmp;
continue;
}
if (a[dep] > a[kmp+1]) {
int tmp = dfs(dep+1,rk+r,0);
r += tmp;
}
}
return r;
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("3.in","r",stdin);
#endif
a[0] = -INF;
int cas = 0;
while (~scanf("%d%d%d%d",&n,&m,&L,&R)) {
cas++; printf("Case %d:\n",cas);
int r = 0;
for (int i=1;i<=m;i++) {
a[1] = i;
r += dfs(2,r,0);
}
}
return 0;
}