题意:有m种小写字符,给定一个长为n的序列,定义编辑距离为序列中相邻两个字母位置差的绝对值之和,其中字母位置是一个1到m的排列
安排一种方案,求编辑距离最小
n<=1e5,m<=20
思路:刚开始不会算贡献,觉得一定要把具体的排列搞出来才能做
其实pos[s[i-1]]和pos[s[i]]之差可以看成字符s[i-1]和字符s[i]被选择的时间的差
也就是说只有一个没有被选,另一个被选的情况下每次都会累计这样的字母对数的贡献
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 typedef unsigned int uint; 5 typedef unsigned long long ull; 6 typedef pair<int,int> PII; 7 typedef pair<ll,ll> Pll; 8 typedef vector<int> VI; 9 typedef vector<PII> VII; 10 //typedef pair<ll,ll>P; 11 #define N 200010 12 #define M 200010 13 #define fi first 14 #define se second 15 #define MP make_pair 16 #define pb push_back 17 #define pi acos(-1) 18 #define mem(a,b) memset(a,b,sizeof(a)) 19 #define rep(i,a,b) for(int i=(int)a;i<=(int)b;i++) 20 #define per(i,a,b) for(int i=(int)a;i>=(int)b;i--) 21 #define lowbit(x) x&(-x) 22 #define Rand (rand()*(1<<16)+rand()) 23 #define id(x) ((x)<=B?(x):m-n/(x)+1) 24 #define ls p<<1 25 #define rs p<<1|1 26 27 const int MOD=1e9+7,inv2=(MOD+1)/2; 28 double eps=1e-4; 29 int INF=1e9; 30 int inf=0x7fffffff; 31 int dx[4]={-1,1,0,0}; 32 int dy[4]={0,0,-1,1}; 33 34 char s[N]; 35 int dp[1<<20],f[21][21]; 36 37 int read() 38 { 39 int v=0,f=1; 40 char c=getchar(); 41 while(c<48||57<c) {if(c=='-') f=-1; c=getchar();} 42 while(48<=c&&c<=57) v=(v<<3)+v+v+c-48,c=getchar(); 43 return v*f; 44 } 45 46 int main() 47 { 48 int n=read(),m=read(); 49 int S=(1<<m)-1; 50 scanf("%s",s+1); 51 rep(i,2,n) 52 { 53 int x=s[i-1]-'a',y=s[i]-'a'; 54 f[x][y]++; 55 f[y][x]++; 56 } 57 rep(i,0,S) dp[i]=INF; 58 dp[0]=0; 59 rep(sta,0,S-1) 60 { 61 int t=0; 62 rep(i,0,m-1) 63 { 64 if(sta>>i&1) continue; 65 rep(j,0,m-1) 66 if(sta>>j&1) t+=f[i][j]; 67 } 68 69 rep(i,0,m-1) 70 { 71 if(sta>>i&1) continue; 72 dp[sta+(1<<i)]=min(dp[sta+(1<<i)],dp[sta]+t); 73 } 74 } 75 printf("%d ",dp[S]); 76 return 0; 77 }