【编码题】字符串S由小写字母构成,长度为n。定义一种操作,每次都可以挑选字符串中任意的两个相邻字母进行交换。询问在至多交换m次之后,字符串中最多有多少个连续的位置上的字母相同?
【编码题】字符串S由小写字母构成,长度为n。定义一种操作,每次都可以挑选字符串中任意的两个相邻字母进行交换。询问在至多交换m次之后,字符串中最多有多少个连续的位置上的字母相同?
第一行为一个字符串S与一个非负整数m。(1 <= |S| <= 1000, 1 <= m <= 1000000)
一个非负整数,表示操作之后,连续最长的相同字母数量。
abcbaa 2
2
使2个字母a连续出现,至少需要3次操作。即把第1个位置上的a移动到第4个位置。 所以在至多操作2次的情况下,最多只能使2个b或2个a连续出现。
dp[i][j] =dp[i + 1][j - 1] + ls.get(j) - ls.get(i) - 1 - (j - i - 1);递推式的意思是:从i+1~j-1已经连续好了,再把 i 和 j 也变成连续的,需要这两个位置的差(ls.get(j) - ls.get(i) - 1),减去里面已经有的(i - j - 1)。
import java.util.*; // 注意类名必须为 Main, 不要有任何 package xxx 信息 public class Main { public static void main(String[] args) { Scanner in = new Scanner(System.in); String s = in.next(); int m = in.nextInt(); Map<Character, List<Integer>> map = new HashMap<>(); for (int i = 0; i < s.length(); ++i) { map.computeIfAbsent(s.charAt(i), k -> new ArrayList<>()).add(i); } int ans = 0; for (List<Integer> ls: map.values()) { int n = ls.size(); int[][] dp = new int[n][n]; for (int i = n - 1; i >= 0; --i) { for (int j = i + 1; j < n; ++j) { dp[i][j] =dp[i + 1][j - 1] + ls.get(j) - ls.get(i) - 1 - (j - i - 1); if (dp[i][j] <= m) ans = Math.max(ans, j - i + 1); } } } System.out.println(ans); } }
import java.util.*; public class Main{ public static void main (String[] args) { Scanner sc = new Scanner(System.in); String str = sc.next(); int m = sc.nextInt(); HashMap<Character, ArrayList<Integer>> table = new HashMap<>(); for(int i=0;i<str.length();i++){ if(!table.containsKey(str.charAt(i))){ int finalI = i; table.put(str.charAt(i),new ArrayList<Integer>(){{add(finalI);}}); }else{ table.get(str.charAt(i)).add(i); } } PriorityQueue<Integer> res = new PriorityQueue<Integer>(Comparator.reverseOrder()); for(Character x: table.keySet()){ PriorityQueue<Integer> temp = new PriorityQueue<Integer>(Comparator.reverseOrder()); for(int i = 0;i<table.get(x).size();i++){ int time = m; int lcount = 1,rcount = 1; PriorityQueue<Integer> dis = new PriorityQueue<Integer>(new Comparator<Integer>(){ @Override public int compare(Integer j, Integer k) { if (Math.abs(j)<Math.abs(k)){ return -1; }else{ return 1; } } }); for(int j=0;j<table.get(x).size();j++){ dis.add(table.get(x).get(j)-table.get(x).get(i)); } while (!dis.isEmpty()){ int test = dis.poll(); if(test <0 && Math.abs(test)<=time){ int cost = (test+lcount); lcount ++; time += cost; }else if(test>0 && test <=time){ int cost = (test-rcount); rcount ++; time -= cost; } } temp.add(lcount+rcount-1); } res.add(temp.poll()); } System.out.println(res.poll()); } }
import java.util.*; public class Main { public static void main(String[] args) { Scanner sc = new Scanner(System.in); String[] strs = sc.nextLine().split(" "); String s = strs[0]; int count = Integer.parseInt(strs[1]); int len = s.length(); int[][] record = new int[len][26]; //记录字符串s的每个位置和26个字母的关系 int[] length = new int[26]; //记录每个字母在规定交换次数内最长的相同字母数量 for(int i = 0; i < len; i++){ record[i][s.charAt(i)-'a'] = 1; } for(int i = 0; i < 26; i++){ int[] position = new int[len]; //对于每个字母,记录字符串s中出现该字母的位置 int k = 0; //字符串s中出现该字母k次 for(int j = 0; j < len; j++){ if(record[j][i] == 1){ position[k] = j; k += 1; } } if(k == 0){ length[i] = 0; }else if(k == 1){ length[i] = 1; }else{ int answer = Integer.MIN_VALUE; for (int p = 0; p < k; p++){ for (int q = p+1; q < k; q++){ int res = dfsSwichCharacter(p, q, position); if(res <= count){ //在规定交换次数内,更新连续的某个相同字母数量 answer = Math.max(answer, q-p+1); } } } length[i] = answer; } } int result = Integer.MIN_VALUE; for(int i : length){ result = Math.max(result, i); } System.out.println(result); } public static int dfsSwichCharacter(int i, int j, int[] position){ if(i == j){ return 0; }else if(i+1 == j){ //说明字符串s中position[i]和position[j]之间不可能再有该字母,所以移动次数就是坐标之差减一 return position[j] - position[i] - 1; }else{ //移动次数相当于是把position[j]的字母移到position[i]隔壁的次数减去这两个位置之间该字母的个数 return dfsSwichCharacter(i+1, j-1, position) + position[j]-position[i]-1 - (j-i-1); } } }
// Javahttps://blog.csdn.net/qq_34385263/article/details/82026285public static void solv(String s, int m){
Map<Character, List> map = new HashMap<>(26);
for (int i = 0; i < s.length(); i++){
char c = s.charAt(i);
List list = map.get(c);
if (list == null)
map.put(c, list = new ArrayList<Integer>(100));
list.add(i);
}
int maxLen = 1;
for (Map.Entry<Character, List> entry : map.entrySet()){
List<Integer> arrayList = entry.getValue();
for (int i = 0; i < arrayList.size(); i++){
int ctr = arrayList.get(i);
int []move = new int[arrayList.size()];
// 获取 move[],表示每个相同字母到中心点 ctr 需要移动的最少步数
for (int j = 0; j < arrayList.size(); j++)
move[j] = (Math.abs(arrayList.get(j) - ctr) -
Math.abs(i - j));
// 排序后,选择移动代价最少的前 k + 1 个
Arrays.sort(move);
int sum = 0;
for (int k = 0; k < move.length; k++){
sum += move[k];
if (sum > m)
break;
if (k + 1 > maxLen)
maxLen = k + 1;
}
}
}
System.out.println(maxLen);
}