传送门:cf 496C
给定n个长为m的字符串,现在要求字符串从上到下遵循字典序,可以通过完整的删除某一列字母来调整,问最少删除多少列能达到使字符串满足字典序的要求。(允许两个字符串完全相同,且允许把所有列都删光)
当前面的字母已经满足字典序大小关系,后面的字母无论怎么样都无法影响字典序,因此从第一列开始处理判断是否要删除。
当某一列中相邻的两行,前面字母的字典序完全相等,上一行的字母大于下一行的字母则该列需要删除。
用flag数组记录下某一行与下一行是否已经满足字典序大小关系,在之后的判断中可以跳过已经满足的行
/******************************************************
* File Name: a.cpp
* Author: kojimai
* Create Time: 2014年12月18日 星期四 00时31分43秒
******************************************************/
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<iostream>
using namespace std;
const int FFF = 1005;
char s[FFF][FFF];
bool flag[FFF],now[FFF];
int main() {
int n,m;
cin >> n >> m;
for(int i = 0;i < n;i++) {
cin >> s[i];
}
memset(now,false,sizeof(now));
int ans = 0;
for(int i = 0;i < m;i++) {
memset(flag,false,sizeof(flag));
bool ok = true;
for(int j = 0;j < n - 1 && ok;j++) {
if(now[j]) continue;
if(s[j][i] > s[j+1][i]) {
ans++;
ok = false;
break;
}
else if(s[j][i] < s[j+1][i]) {
flag[j] = true;
}
}
if(ok)
for(int j = 0;j < n;j++) {
if(flag[j])
now[j] = true;
}
//cout<<i<<' '<<ans<<endl;
}
cout << ans << endl;
return 0;
}
n,m = map(int,raw_input().split())
s = []
for i in range(0,n):
ss = raw_input()
s.append(ss)
ans = 0
flag = [0] * n
for col in range(0,m):
now = [0] * n
ok = True
for i in range(0,n-1):
if flag[i] == 1:
continue
if s[i][col] > s[i+1][col]:
ans = ans + 1
ok = False
break;
elif s[i][col] < s[i+1][col]:
now[i] = 1
if ok == True:
for i in range(0,n):
flag[i] = flag[i] or now[i]
print ans